Remove windows line ending from repo files.

Somehow these files got submitted with win32 line
endings.  Maybe its not worth fixing?

BUG=

Review URL: https://codereview.chromium.org/10908249

git-svn-id: https://nativeclient-sdk.googlecode.com/svn/trunk/src@1419 050acbb0-2703-11df-ab0a-9f3f633ae91d
diff --git a/InstallerResources/create_ppapi_platform.py b/InstallerResources/create_ppapi_platform.py
index bee321d..252ae5a 100644
--- a/InstallerResources/create_ppapi_platform.py
+++ b/InstallerResources/create_ppapi_platform.py
@@ -1,206 +1,206 @@
-#!/usr/bin/env python

-# Copyright (c) 2012 The Chromium Authors. All rights reserved.

-# Use of this source code is governed by a BSD-style license that can be

-# found in the LICENSE file.

-

-""" This script creates the PPAPI project settings template.

-

-For copyright reasons, we should not directly distribute the PPAPI template

-because it is nearly a clone of the Win32 template which is Copyrighted.

-Instead, this script copies the existing Win32 template from the user's system

-and intelligently modifies the copy to be the PPAPI template.

-"""

-

-import os

-import optparse

-import shutil

-import string

-import xml_patch

-import third_party.etree.ElementTree as ElementTree

-

-

-PEPPER_PLATFORM_NAME = 'PPAPI'

-

-DEFAULT_MS_BUILD_DIRECTORY = os.path.expandvars('%ProgramFiles(x86)%\\MSBuild')

-

-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

-

-PLATFORM_FILES = [

-    ('Microsoft.Cpp.Win32.default.props',

-     'Microsoft.Cpp.[platform].default.props.patch',

-     'Microsoft.Cpp.PPAPI.default.props'),

-    ('Microsoft.Cpp.Win32.props',

-     'Microsoft.Cpp.[platform].props.patch',

-     'Microsoft.Cpp.PPAPI.props'),

-    ('Microsoft.Cpp.Win32.targets',

-     'Microsoft.Cpp.[platform].targets.patch',

-     'Microsoft.Cpp.PPAPI.targets'),

-    ('PlatformToolsets\\v100\\Microsoft.Cpp.Win32.v100.props',

-     'PlatformToolsets\\v100\\Microsoft.Cpp.[platform].v100.props.patch',

-     'PlatformToolsets\\v100\\Microsoft.Cpp.PPAPI.v100.props'),

-    ('PlatformToolsets\\v100\\Microsoft.Cpp.Win32.v100.targets',

-     'PlatformToolsets\\v100\\Microsoft.Cpp.[platform].v100.targets.patch',

-     'PlatformToolsets\\v100\\Microsoft.Cpp.PPAPI.v100.targets')]

-

-UI_FILES = [

-    ('general.xml',

-     'Props\\ppapi_general.xml.patch',

-     'Props\\ppapi_general.xml'),

-    ('general_ps.xml',

-     'Props\\ppapi_general_ps.xml.patch',

-     'Props\\ppapi_general_ps.xml')]

-

-COPY_FILES = [

-    'ImportAfter\\PPAPI.override.props']

-

-

-def PrependCopyright(source_file_name, dest_file_name):

-  """Adds the copyright notice from source file to the dest file.

-

-  Since the patch_xml function does not read comments, the copyright is skipped

-  during the initial copy. This function adds it back and also attaches a

-  notice that the file was based on source_file_name and slightly modified.

-

-  Args:

-    source_file_name: The original Win32 file.

-    dest_file_name: The existing PPAPI file.

-

-  Returns:

-    None.

-  """

-  with open(source_file_name, 'r') as source_file:

-    in_copyright = False

-    copyright_notice = ''

-    for line in source_file:

-      if '<!--' in line:

-        in_copyright = True

-      if in_copyright:

-        copyright_notice += line

-      if '-->' in line:

-        in_copyright = False

-        break

-

-  with open(dest_file_name, 'r') as original:

-    xml_data = original.read()

-

-  chrome_notice = ('<!-- This file has been copied and modified from %s during '

-                   'the installation process. -->\n\n' % (source_file_name))

-

-  with open(dest_file_name, 'w') as changed:

-    changed.writelines(copyright_notice + chrome_notice + xml_data)

-

-

-def CreateTemplateFile(source, patch, dest):

-  """Creates a single PPAPI template file.

-

-  Args:

-    source: The path source file to create from.

-    patch: The path to the patch file to apply.

-    dest: The path to the file to create.

-  Returns:

-    None.

-  """

-  source_xml = ElementTree.parse(source)

-  patch_xml = ElementTree.parse(patch)

-  modified_xml = xml_patch.PatchXML(source_xml, patch_xml)

-

-  if not os.path.exists(os.path.dirname(dest)):

-    os.makedirs(os.path.dirname(dest))

-

-  FixAttributesNamespace(modified_xml)

-  default_namespace = GetDefaultNamespace(modified_xml)

-  modified_xml.write(dest, default_namespace=default_namespace)

-  PrependCopyright(source, dest)

-

-

-def GetDefaultNamespace(tree):

-  # Returns the uri (namespace identifier) of the root element.

-  tag = tree.getroot().tag

-  if tag.startswith("{"):

-    uri, rest = tag[1:].rsplit("}", 1)

-    return uri

-  else:

-    return None

-

-

-def FixAttributesNamespace(tree):

-  # ElementTree's implementation seems to be broken in that attributes

-  # do not inherit the default namespace of their node or parent nodes.

-  # This causes issues with ElementTree.write() when using a default namespace.

-  # Since the attributes do not have a namespace, the code that collects a

-  # mapping between local names and qualified names (with a namespace) breaks.

-  # The work-around is to give all attributes the default namespace.

-  default_namespace = GetDefaultNamespace(tree)

-  for elem in tree.getroot().getiterator():

-    new_attrib = dict()

-    for key, value in elem.attrib.items():

-      # If the attribute does not have a namespace yet then give it one.

-      if key[:1] != "{":

-        new_key = "{%s}%s" % (default_namespace, key)

-        new_attrib[new_key] = value

-      else:

-        new_attrib[key] = value

-    elem.attrib = new_attrib

-

-

-def CreatePPAPI(msbuild_dir):

-  """Creates the PPAPI template.

-

-  Args:

-    msbuild_dir: The path to the MSBuild installation.

-

-  Returns:

-    Nothing.

-

-  Raises:

-    Exception indicating Win32 platform was not found.

-  """

-  if not os.path.exists(msbuild_dir):

-    raise Exception('MSBuild directory was not found!')

-

-  install_dir = os.path.join(msbuild_dir, 'Microsoft.Cpp\\v4.0\\Platforms')

-

-  # Note 1033 is code for the english language.

-  ui_xml_dir = os.path.join(msbuild_dir, 'Microsoft.Cpp\\v4.0\\1033')

-

-  win32_dir = os.path.join(install_dir, 'Win32')

-  ppapi_dir = os.path.join(install_dir, PEPPER_PLATFORM_NAME)

-  patch_dir = os.path.join(SCRIPT_DIR, 'PPAPI_Patch')

-

-  if not os.path.exists(win32_dir):

-    raise Exception('Win32 platform is not installed on this machine!')

-

-  for template_creation in PLATFORM_FILES:

-    CreateTemplateFile(

-        os.path.join(win32_dir, template_creation[0]),

-        os.path.join(patch_dir, template_creation[1]),

-        os.path.join(ppapi_dir, template_creation[2]))

-

-  for template_creation in UI_FILES:

-    CreateTemplateFile(

-        os.path.join(ui_xml_dir, template_creation[0]),

-        os.path.join(patch_dir, template_creation[1]),

-        os.path.join(ppapi_dir, template_creation[2]))

-

-  for file_name in COPY_FILES:

-    copy_from = os.path.join(patch_dir, file_name)

-    copy_to = os.path.join(ppapi_dir, file_name)

-    if not os.path.exists(os.path.dirname(copy_to)):

-      os.makedirs(os.path.dirname(copy_to))

-    shutil.copyfile(copy_from, copy_to)

-

-  shutil.copyfile(

-      os.path.join(win32_dir, 'Microsoft.Build.CPPTasks.Win32.dll'),

-      os.path.join(ppapi_dir, 'Microsoft.Build.CPPTasks.PPAPI.dll'))

-

-

-def main():

-  parser = optparse.OptionParser(usage='Usage: %prog [options]')

-  parser.add_option('-b', '--msbuild-path', dest='msbuild_path',

-      default=DEFAULT_MS_BUILD_DIRECTORY,

-      help='Provide the path to the MSBuild directory', metavar='PATH')

-  (options, args) = parser.parse_args()

-  CreatePPAPI(options.msbuild_path)

-

-if __name__ == '__main__':

-  main()

+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" This script creates the PPAPI project settings template.
+
+For copyright reasons, we should not directly distribute the PPAPI template
+because it is nearly a clone of the Win32 template which is Copyrighted.
+Instead, this script copies the existing Win32 template from the user's system
+and intelligently modifies the copy to be the PPAPI template.
+"""
+
+import os
+import optparse
+import shutil
+import string
+import xml_patch
+import third_party.etree.ElementTree as ElementTree
+
+
+PEPPER_PLATFORM_NAME = 'PPAPI'
+
+DEFAULT_MS_BUILD_DIRECTORY = os.path.expandvars('%ProgramFiles(x86)%\\MSBuild')
+
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+PLATFORM_FILES = [
+    ('Microsoft.Cpp.Win32.default.props',
+     'Microsoft.Cpp.[platform].default.props.patch',
+     'Microsoft.Cpp.PPAPI.default.props'),
+    ('Microsoft.Cpp.Win32.props',
+     'Microsoft.Cpp.[platform].props.patch',
+     'Microsoft.Cpp.PPAPI.props'),
+    ('Microsoft.Cpp.Win32.targets',
+     'Microsoft.Cpp.[platform].targets.patch',
+     'Microsoft.Cpp.PPAPI.targets'),
+    ('PlatformToolsets\\v100\\Microsoft.Cpp.Win32.v100.props',
+     'PlatformToolsets\\v100\\Microsoft.Cpp.[platform].v100.props.patch',
+     'PlatformToolsets\\v100\\Microsoft.Cpp.PPAPI.v100.props'),
+    ('PlatformToolsets\\v100\\Microsoft.Cpp.Win32.v100.targets',
+     'PlatformToolsets\\v100\\Microsoft.Cpp.[platform].v100.targets.patch',
+     'PlatformToolsets\\v100\\Microsoft.Cpp.PPAPI.v100.targets')]
+
+UI_FILES = [
+    ('general.xml',
+     'Props\\ppapi_general.xml.patch',
+     'Props\\ppapi_general.xml'),
+    ('general_ps.xml',
+     'Props\\ppapi_general_ps.xml.patch',
+     'Props\\ppapi_general_ps.xml')]
+
+COPY_FILES = [
+    'ImportAfter\\PPAPI.override.props']
+
+
+def PrependCopyright(source_file_name, dest_file_name):
+  """Adds the copyright notice from source file to the dest file.
+
+  Since the patch_xml function does not read comments, the copyright is skipped
+  during the initial copy. This function adds it back and also attaches a
+  notice that the file was based on source_file_name and slightly modified.
+
+  Args:
+    source_file_name: The original Win32 file.
+    dest_file_name: The existing PPAPI file.
+
+  Returns:
+    None.
+  """
+  with open(source_file_name, 'r') as source_file:
+    in_copyright = False
+    copyright_notice = ''
+    for line in source_file:
+      if '<!--' in line:
+        in_copyright = True
+      if in_copyright:
+        copyright_notice += line
+      if '-->' in line:
+        in_copyright = False
+        break
+
+  with open(dest_file_name, 'r') as original:
+    xml_data = original.read()
+
+  chrome_notice = ('<!-- This file has been copied and modified from %s during '
+                   'the installation process. -->\n\n' % (source_file_name))
+
+  with open(dest_file_name, 'w') as changed:
+    changed.writelines(copyright_notice + chrome_notice + xml_data)
+
+
+def CreateTemplateFile(source, patch, dest):
+  """Creates a single PPAPI template file.
+
+  Args:
+    source: The path source file to create from.
+    patch: The path to the patch file to apply.
+    dest: The path to the file to create.
+  Returns:
+    None.
+  """
+  source_xml = ElementTree.parse(source)
+  patch_xml = ElementTree.parse(patch)
+  modified_xml = xml_patch.PatchXML(source_xml, patch_xml)
+
+  if not os.path.exists(os.path.dirname(dest)):
+    os.makedirs(os.path.dirname(dest))
+
+  FixAttributesNamespace(modified_xml)
+  default_namespace = GetDefaultNamespace(modified_xml)
+  modified_xml.write(dest, default_namespace=default_namespace)
+  PrependCopyright(source, dest)
+
+
+def GetDefaultNamespace(tree):
+  # Returns the uri (namespace identifier) of the root element.
+  tag = tree.getroot().tag
+  if tag.startswith("{"):
+    uri, rest = tag[1:].rsplit("}", 1)
+    return uri
+  else:
+    return None
+
+
+def FixAttributesNamespace(tree):
+  # ElementTree's implementation seems to be broken in that attributes
+  # do not inherit the default namespace of their node or parent nodes.
+  # This causes issues with ElementTree.write() when using a default namespace.
+  # Since the attributes do not have a namespace, the code that collects a
+  # mapping between local names and qualified names (with a namespace) breaks.
+  # The work-around is to give all attributes the default namespace.
+  default_namespace = GetDefaultNamespace(tree)
+  for elem in tree.getroot().getiterator():
+    new_attrib = dict()
+    for key, value in elem.attrib.items():
+      # If the attribute does not have a namespace yet then give it one.
+      if key[:1] != "{":
+        new_key = "{%s}%s" % (default_namespace, key)
+        new_attrib[new_key] = value
+      else:
+        new_attrib[key] = value
+    elem.attrib = new_attrib
+
+
+def CreatePPAPI(msbuild_dir):
+  """Creates the PPAPI template.
+
+  Args:
+    msbuild_dir: The path to the MSBuild installation.
+
+  Returns:
+    Nothing.
+
+  Raises:
+    Exception indicating Win32 platform was not found.
+  """
+  if not os.path.exists(msbuild_dir):
+    raise Exception('MSBuild directory was not found!')
+
+  install_dir = os.path.join(msbuild_dir, 'Microsoft.Cpp\\v4.0\\Platforms')
+
+  # Note 1033 is code for the english language.
+  ui_xml_dir = os.path.join(msbuild_dir, 'Microsoft.Cpp\\v4.0\\1033')
+
+  win32_dir = os.path.join(install_dir, 'Win32')
+  ppapi_dir = os.path.join(install_dir, PEPPER_PLATFORM_NAME)
+  patch_dir = os.path.join(SCRIPT_DIR, 'PPAPI_Patch')
+
+  if not os.path.exists(win32_dir):
+    raise Exception('Win32 platform is not installed on this machine!')
+
+  for template_creation in PLATFORM_FILES:
+    CreateTemplateFile(
+        os.path.join(win32_dir, template_creation[0]),
+        os.path.join(patch_dir, template_creation[1]),
+        os.path.join(ppapi_dir, template_creation[2]))
+
+  for template_creation in UI_FILES:
+    CreateTemplateFile(
+        os.path.join(ui_xml_dir, template_creation[0]),
+        os.path.join(patch_dir, template_creation[1]),
+        os.path.join(ppapi_dir, template_creation[2]))
+
+  for file_name in COPY_FILES:
+    copy_from = os.path.join(patch_dir, file_name)
+    copy_to = os.path.join(ppapi_dir, file_name)
+    if not os.path.exists(os.path.dirname(copy_to)):
+      os.makedirs(os.path.dirname(copy_to))
+    shutil.copyfile(copy_from, copy_to)
+
+  shutil.copyfile(
+      os.path.join(win32_dir, 'Microsoft.Build.CPPTasks.Win32.dll'),
+      os.path.join(ppapi_dir, 'Microsoft.Build.CPPTasks.PPAPI.dll'))
+
+
+def main():
+  parser = optparse.OptionParser(usage='Usage: %prog [options]')
+  parser.add_option('-b', '--msbuild-path', dest='msbuild_path',
+      default=DEFAULT_MS_BUILD_DIRECTORY,
+      help='Provide the path to the MSBuild directory', metavar='PATH')
+  (options, args) = parser.parse_args()
+  CreatePPAPI(options.msbuild_path)
+
+if __name__ == '__main__':
+  main()
diff --git a/InstallerResources/install.py b/InstallerResources/install.py
index 0dd6d6c..efc35e4 100644
--- a/InstallerResources/install.py
+++ b/InstallerResources/install.py
@@ -1,193 +1,193 @@
-#!/usr/bin/env python

-# Copyright (c) 2012 The Chromium Authors. All rights reserved.

-# Use of this source code is governed by a BSD-style license that can be

-# found in the LICENSE file.

-

-"""Copies necessary add-in files into place to install the add-in.

-

-This script will copy the necessary files for the Visual Studio add-in

-to where Visual Studio can find them. It assumes the current directory

-contains the necessary files to copy.

-"""

-

-import create_ppapi_platform

-import ctypes

-import os

-import optparse

-import platform

-import shutil

-import sys

-

-NACL_PLATFORM_NAME = 'NaCl'

-PEPPER_PLATFORM_NAME = 'PPAPI'

-

-DEFAULT_VS_USER_DIRECTORY = os.path.expandvars(

-    '%USERPROFILE%\\My Documents\\Visual Studio 2010')

-

-DEFAULT_MS_BUILD_DIRECTORY = os.path.expandvars('%ProgramFiles(x86)%\\MSBuild')

-

-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

-

-ADDIN_FILES = ['NativeClientVSAddIn.AddIn', 'NativeClientVSAddIn.dll']

-

-class InstallError(Exception):

-  """Error class for this installer indicating a fatal but expected error."""

-  pass

-

-def UninstallDirectory(directory):

-  if os.path.exists(directory):

-    shutil.rmtree(directory)

-    print 'Removed: %s' % (directory)

-  else:

-    print 'Failed to remove non-existant directory: %s' % (directory)

-

-

-def UninstallFile(file_path):

-  if os.path.exists(file_path):

-    os.remove(file_path)

-    print 'Removed: %s' % (file_path)

-  else:

-    print 'Failed to remove non-existant file: %s' % (file_path)

-

-

-def Uninstall(nacl_directory, pepper_directory, addin_directory):

-  UninstallDirectory(nacl_directory)

-  UninstallDirectory(pepper_directory)

-  for file_name in ADDIN_FILES:

-    UninstallFile(os.path.join(addin_directory, file_name))

-

-

-def main():

-  parser = optparse.OptionParser(usage='Usage: %prog [options]')

-  parser.add_option('-b', '--msbuild-path', dest='msbuild_path',

-      default=DEFAULT_MS_BUILD_DIRECTORY, metavar='PATH',

-      help='Provide the path to the MSBuild directory')

-  parser.add_option('-a', '--vsuser-path', dest='vsuser_path',

-      default=DEFAULT_VS_USER_DIRECTORY, metavar='PATH',

-      help='Provide the path to the Visual Studio user directory')

-  parser.add_option('-f', '--force', action="store_true", dest='overwrite',

-      default=False, help='Force an overwrite of existing files')

-  parser.add_option('-p', '--ppapi', action="store_true", dest='install_ppapi',

-      help='Install PPAPI template without asking.')

-  parser.add_option('-n', '--no-ppapi', action="store_false",

-      dest='install_ppapi', help='Do not install PPAPI template and do not ask')

-  parser.add_option('-u', '--uninstall', action="store_true",

-      dest='uninstall', help='Remove the add-in.')

-  (options, args) = parser.parse_args()

-

-  print "*************************************************"

-  print "Native-Client Visual Studio 2010 Add-in Installer"

-  print "*************************************************\n"

-  print "Please ensure Visual Studio and MSBuild are closed " \

-        "during installation.\n"

-

-  if platform.system() != 'Windows':

-    raise InstallError('Must install to Windows system')

-

-  if sys.version_info < (2, 6, 2):

-    print "\n\nWARNING: Only python version 2.6.2 or greater is supported. " \

-          "Current version is %s\n\n" % (sys.version_info[:3],)

-

-  # Admin is needed to write to the default platform directory.

-  if ctypes.windll.shell32.IsUserAnAdmin() != 1:

-    raise InstallError("Not running as administrator. The install script needs "

-                       "write access to protected Visual Studio directories.")

-

-  # Ensure install directories exist.

-  if not os.path.exists(options.vsuser_path):

-    raise InstallError("Could not find user Visual Studio directory: %s" % (

-        options.vsuser_path))

-  if not os.path.exists(options.msbuild_path):

-    raise InstallError("Could not find MS Build directory: %s" % (

-        options.msbuild_path))

-

-  addin_directory = os.path.join(options.vsuser_path, 'Addins')

-  platform_directory = os.path.join(

-      options.msbuild_path, 'Microsoft.Cpp\\v4.0\\Platforms')

-  nacl_directory = os.path.join(platform_directory, NACL_PLATFORM_NAME)

-  pepper_directory = os.path.join(platform_directory, PEPPER_PLATFORM_NAME)

-

-  # If uninstalling then redirect to uninstall program.

-  if options.uninstall:

-    Uninstall(nacl_directory, pepper_directory, addin_directory)

-    print "\nUninstall complete!\n"

-    exit(0)

-

-  if not os.path.exists(platform_directory):

-    raise InstallError("Could not find path: %s" % platform_directory)

-  if not os.path.exists(addin_directory):

-    os.mkdir(addin_directory)

-

-  # Ensure environment variables are set.

-  nacl_sdk_root = os.getenv('NACL_SDK_ROOT', None)

-  chrome_path = os.getenv('CHROME_PATH', None)

-  if nacl_sdk_root is None:

-    raise InstallError('Environment Variable NACL_SDK_ROOT is not set')

-  if chrome_path is None:

-    raise InstallError('Environment Variable CHROME_PATH is not set')

-

-  # Remove existing installation.

-  if os.path.exists(nacl_directory) or os.path.exists(pepper_directory):

-    # If not forced then ask user permission.

-    if not options.overwrite:

-      print "\nWarning: Pre-existing add-in installation will be overwritten."

-      print "Continue? ((Yes))/((No))"

-      remove_answer = raw_input().strip()

-      if not (remove_answer.lower() == "yes" or remove_answer.lower() == "y"):

-        raise InstallError('User did not allow overwrite of existing install.')

-    print "Removing existing install..."

-    Uninstall(nacl_directory, pepper_directory, addin_directory)

-

-  # Ask user before installing PPAPI template.

-  if options.install_ppapi is None:

-    print "\n"

-    print "Set up configuration to enable Pepper development " \

-          "with Visual Studio?"

-    print "((Yes)) - I want to create and copy relevant files into a " \

-           "Pepper subdirectory"

-    print "((No)) - I am not interested or will set up the configuration later"

-    ppapi_answer = raw_input().strip()

-    if ppapi_answer.lower() == "yes" or ppapi_answer.lower() == "y":

-      options.install_ppapi = True

-      print "Confirmed installer will include PPAPI platform."

-    else:

-      options.install_ppapi = False

-      print "Will not install PPAPI platform during installation."

-

-  print "\nBegin installing components..."

-

-  try:

-    # Copy the necessary files into place.

-    for file_name in ADDIN_FILES:

-      shutil.copy(os.path.join(SCRIPT_DIR, file_name), addin_directory)

-    print "Add-in installed."

-

-    shutil.copytree(os.path.join(SCRIPT_DIR, 'NaCl'), nacl_directory)

-    print "NaCl platform installed."

-

-    if options.install_ppapi:

-      create_ppapi_platform.CreatePPAPI(options.msbuild_path)

-      print "PPAPI platform installed."

-  except:

-    print "\nException occured! Rolling back install...\n"

-    Uninstall(nacl_directory, pepper_directory, addin_directory)

-    raise

-  else:

-    print "\nInstallation complete!\n"

-

-if __name__ == '__main__':

-  try:

-    main()

-  except InstallError as e:

-    print

-    print e

-  except shutil.Error as e:

-    print "Error while copying file. Please ensure file is not in use."

-    print e

-  except WindowsError as e:

-    if e.winerror == 5:

-      print "Access denied error.  Please ensure Visual Studio and MSBuild"

-      print "processes are closed."

-    else:

-      raise

-

+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Copies necessary add-in files into place to install the add-in.
+
+This script will copy the necessary files for the Visual Studio add-in
+to where Visual Studio can find them. It assumes the current directory
+contains the necessary files to copy.
+"""
+
+import create_ppapi_platform
+import ctypes
+import os
+import optparse
+import platform
+import shutil
+import sys
+
+NACL_PLATFORM_NAME = 'NaCl'
+PEPPER_PLATFORM_NAME = 'PPAPI'
+
+DEFAULT_VS_USER_DIRECTORY = os.path.expandvars(
+    '%USERPROFILE%\\My Documents\\Visual Studio 2010')
+
+DEFAULT_MS_BUILD_DIRECTORY = os.path.expandvars('%ProgramFiles(x86)%\\MSBuild')
+
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+ADDIN_FILES = ['NativeClientVSAddIn.AddIn', 'NativeClientVSAddIn.dll']
+
+class InstallError(Exception):
+  """Error class for this installer indicating a fatal but expected error."""
+  pass
+
+def UninstallDirectory(directory):
+  if os.path.exists(directory):
+    shutil.rmtree(directory)
+    print 'Removed: %s' % (directory)
+  else:
+    print 'Failed to remove non-existant directory: %s' % (directory)
+
+
+def UninstallFile(file_path):
+  if os.path.exists(file_path):
+    os.remove(file_path)
+    print 'Removed: %s' % (file_path)
+  else:
+    print 'Failed to remove non-existant file: %s' % (file_path)
+
+
+def Uninstall(nacl_directory, pepper_directory, addin_directory):
+  UninstallDirectory(nacl_directory)
+  UninstallDirectory(pepper_directory)
+  for file_name in ADDIN_FILES:
+    UninstallFile(os.path.join(addin_directory, file_name))
+
+
+def main():
+  parser = optparse.OptionParser(usage='Usage: %prog [options]')
+  parser.add_option('-b', '--msbuild-path', dest='msbuild_path',
+      default=DEFAULT_MS_BUILD_DIRECTORY, metavar='PATH',
+      help='Provide the path to the MSBuild directory')
+  parser.add_option('-a', '--vsuser-path', dest='vsuser_path',
+      default=DEFAULT_VS_USER_DIRECTORY, metavar='PATH',
+      help='Provide the path to the Visual Studio user directory')
+  parser.add_option('-f', '--force', action="store_true", dest='overwrite',
+      default=False, help='Force an overwrite of existing files')
+  parser.add_option('-p', '--ppapi', action="store_true", dest='install_ppapi',
+      help='Install PPAPI template without asking.')
+  parser.add_option('-n', '--no-ppapi', action="store_false",
+      dest='install_ppapi', help='Do not install PPAPI template and do not ask')
+  parser.add_option('-u', '--uninstall', action="store_true",
+      dest='uninstall', help='Remove the add-in.')
+  (options, args) = parser.parse_args()
+
+  print "*************************************************"
+  print "Native-Client Visual Studio 2010 Add-in Installer"
+  print "*************************************************\n"
+  print "Please ensure Visual Studio and MSBuild are closed " \
+        "during installation.\n"
+
+  if platform.system() != 'Windows':
+    raise InstallError('Must install to Windows system')
+
+  if sys.version_info < (2, 6, 2):
+    print "\n\nWARNING: Only python version 2.6.2 or greater is supported. " \
+          "Current version is %s\n\n" % (sys.version_info[:3],)
+
+  # Admin is needed to write to the default platform directory.
+  if ctypes.windll.shell32.IsUserAnAdmin() != 1:
+    raise InstallError("Not running as administrator. The install script needs "
+                       "write access to protected Visual Studio directories.")
+
+  # Ensure install directories exist.
+  if not os.path.exists(options.vsuser_path):
+    raise InstallError("Could not find user Visual Studio directory: %s" % (
+        options.vsuser_path))
+  if not os.path.exists(options.msbuild_path):
+    raise InstallError("Could not find MS Build directory: %s" % (
+        options.msbuild_path))
+
+  addin_directory = os.path.join(options.vsuser_path, 'Addins')
+  platform_directory = os.path.join(
+      options.msbuild_path, 'Microsoft.Cpp\\v4.0\\Platforms')
+  nacl_directory = os.path.join(platform_directory, NACL_PLATFORM_NAME)
+  pepper_directory = os.path.join(platform_directory, PEPPER_PLATFORM_NAME)
+
+  # If uninstalling then redirect to uninstall program.
+  if options.uninstall:
+    Uninstall(nacl_directory, pepper_directory, addin_directory)
+    print "\nUninstall complete!\n"
+    exit(0)
+
+  if not os.path.exists(platform_directory):
+    raise InstallError("Could not find path: %s" % platform_directory)
+  if not os.path.exists(addin_directory):
+    os.mkdir(addin_directory)
+
+  # Ensure environment variables are set.
+  nacl_sdk_root = os.getenv('NACL_SDK_ROOT', None)
+  chrome_path = os.getenv('CHROME_PATH', None)
+  if nacl_sdk_root is None:
+    raise InstallError('Environment Variable NACL_SDK_ROOT is not set')
+  if chrome_path is None:
+    raise InstallError('Environment Variable CHROME_PATH is not set')
+
+  # Remove existing installation.
+  if os.path.exists(nacl_directory) or os.path.exists(pepper_directory):
+    # If not forced then ask user permission.
+    if not options.overwrite:
+      print "\nWarning: Pre-existing add-in installation will be overwritten."
+      print "Continue? ((Yes))/((No))"
+      remove_answer = raw_input().strip()
+      if not (remove_answer.lower() == "yes" or remove_answer.lower() == "y"):
+        raise InstallError('User did not allow overwrite of existing install.')
+    print "Removing existing install..."
+    Uninstall(nacl_directory, pepper_directory, addin_directory)
+
+  # Ask user before installing PPAPI template.
+  if options.install_ppapi is None:
+    print "\n"
+    print "Set up configuration to enable Pepper development " \
+          "with Visual Studio?"
+    print "((Yes)) - I want to create and copy relevant files into a " \
+           "Pepper subdirectory"
+    print "((No)) - I am not interested or will set up the configuration later"
+    ppapi_answer = raw_input().strip()
+    if ppapi_answer.lower() == "yes" or ppapi_answer.lower() == "y":
+      options.install_ppapi = True
+      print "Confirmed installer will include PPAPI platform."
+    else:
+      options.install_ppapi = False
+      print "Will not install PPAPI platform during installation."
+
+  print "\nBegin installing components..."
+
+  try:
+    # Copy the necessary files into place.
+    for file_name in ADDIN_FILES:
+      shutil.copy(os.path.join(SCRIPT_DIR, file_name), addin_directory)
+    print "Add-in installed."
+
+    shutil.copytree(os.path.join(SCRIPT_DIR, 'NaCl'), nacl_directory)
+    print "NaCl platform installed."
+
+    if options.install_ppapi:
+      create_ppapi_platform.CreatePPAPI(options.msbuild_path)
+      print "PPAPI platform installed."
+  except:
+    print "\nException occured! Rolling back install...\n"
+    Uninstall(nacl_directory, pepper_directory, addin_directory)
+    raise
+  else:
+    print "\nInstallation complete!\n"
+
+if __name__ == '__main__':
+  try:
+    main()
+  except InstallError as e:
+    print
+    print e
+  except shutil.Error as e:
+    print "Error while copying file. Please ensure file is not in use."
+    print e
+  except WindowsError as e:
+    if e.winerror == 5:
+      print "Access denied error.  Please ensure Visual Studio and MSBuild"
+      print "processes are closed."
+    else:
+      raise
+
diff --git a/InstallerResources/third_party/__init__.py b/InstallerResources/third_party/__init__.py
index 5b6a968..93723c7 100644
--- a/InstallerResources/third_party/__init__.py
+++ b/InstallerResources/third_party/__init__.py
@@ -1,31 +1,31 @@
-"""Third party includes for the installer.

-

-Module contains:

-etree -- The ElementTree XML library.  This is a subset of the full

-       ElementTree XML release.

-

-"""

-

-

-__all__ = ["etree"]

-

-_MINIMUM_XMLPLUS_VERSION = (0, 8, 4)

-

-

-try:

-    import _xmlplus

-except ImportError:

-    pass

-else:

-    try:

-        v = _xmlplus.version_info

-    except AttributeError:

-        # _xmlplus is too old; ignore it

-        pass

-    else:

-        if v >= _MINIMUM_XMLPLUS_VERSION:

-            import sys

-            _xmlplus.__path__.extend(__path__)

-            sys.modules[__name__] = _xmlplus

-        else:

-            del v

+"""Third party includes for the installer.
+
+Module contains:
+etree -- The ElementTree XML library.  This is a subset of the full
+       ElementTree XML release.
+
+"""
+
+
+__all__ = ["etree"]
+
+_MINIMUM_XMLPLUS_VERSION = (0, 8, 4)
+
+
+try:
+    import _xmlplus
+except ImportError:
+    pass
+else:
+    try:
+        v = _xmlplus.version_info
+    except AttributeError:
+        # _xmlplus is too old; ignore it
+        pass
+    else:
+        if v >= _MINIMUM_XMLPLUS_VERSION:
+            import sys
+            _xmlplus.__path__.extend(__path__)
+            sys.modules[__name__] = _xmlplus
+        else:
+            del v
diff --git a/InstallerResources/third_party/etree/ElementInclude.py b/InstallerResources/third_party/etree/ElementInclude.py
index 967d85c..84fd754 100644
--- a/InstallerResources/third_party/etree/ElementInclude.py
+++ b/InstallerResources/third_party/etree/ElementInclude.py
@@ -1,143 +1,143 @@
-#

-# ElementTree

-# $Id: ElementInclude.py 3375 2008-02-13 08:05:08Z fredrik $

-#

-# limited xinclude support for element trees

-#

-# history:

-# 2003-08-15 fl   created

-# 2003-11-14 fl   fixed default loader

-#

-# Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.

-#

-# fredrik@pythonware.com

-# http://www.pythonware.com

-#

-# --------------------------------------------------------------------

-# The ElementTree toolkit is

-#

-# Copyright (c) 1999-2008 by Fredrik Lundh

-#

-# By obtaining, using, and/or copying this software and/or its

-# associated documentation, you agree that you have read, understood,

-# and will comply with the following terms and conditions:

-#

-# Permission to use, copy, modify, and distribute this software and

-# its associated documentation for any purpose and without fee is

-# hereby granted, provided that the above copyright notice appears in

-# all copies, and that both that copyright notice and this permission

-# notice appear in supporting documentation, and that the name of

-# Secret Labs AB or the author not be used in advertising or publicity

-# pertaining to distribution of the software without specific, written

-# prior permission.

-#

-# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD

-# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-

-# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR

-# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY

-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS

-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE

-# OF THIS SOFTWARE.

-# --------------------------------------------------------------------

-

-# Licensed to PSF under a Contributor Agreement.

-# See http://www.python.org/psf/license for licensing details.

-

-##

-# Limited XInclude support for the ElementTree package.

-##

-

-import copy

-from . import ElementTree

-

-XINCLUDE = "{http://www.w3.org/2001/XInclude}"

-

-XINCLUDE_INCLUDE = XINCLUDE + "include"

-XINCLUDE_FALLBACK = XINCLUDE + "fallback"

-

-##

-# Fatal include error.

-

-class FatalIncludeError(SyntaxError):

-    pass

-

-##

-# Default loader.  This loader reads an included resource from disk.

-#

-# @param href Resource reference.

-# @param parse Parse mode.  Either "xml" or "text".

-# @param encoding Optional text encoding.

-# @return The expanded resource.  If the parse mode is "xml", this

-#    is an ElementTree instance.  If the parse mode is "text", this

-#    is a Unicode string.  If the loader fails, it can return None

-#    or raise an IOError exception.

-# @throws IOError If the loader fails to load the resource.

-

-def default_loader(href, parse, encoding=None):

-    file = open(href)

-    if parse == "xml":

-        data = ElementTree.parse(file).getroot()

-    else:

-        data = file.read()

-        if encoding:

-            data = data.decode(encoding)

-    file.close()

-    return data

-

-##

-# Expand XInclude directives.

-#

-# @param elem Root element.

-# @param loader Optional resource loader.  If omitted, it defaults

-#     to {@link default_loader}.  If given, it should be a callable

-#     that implements the same interface as <b>default_loader</b>.

-# @throws FatalIncludeError If the function fails to include a given

-#     resource, or if the tree contains malformed XInclude elements.

-# @throws IOError If the function fails to load a given resource.

-

-def include(elem, loader=None):

-    if loader is None:

-        loader = default_loader

-    # look for xinclude elements

-    i = 0

-    while i < len(elem):

-        e = elem[i]

-        if e.tag == XINCLUDE_INCLUDE:

-            # process xinclude directive

-            href = e.get("href")

-            parse = e.get("parse", "xml")

-            if parse == "xml":

-                node = loader(href, parse)

-                if node is None:

-                    raise FatalIncludeError(

-                        "cannot load %r as %r" % (href, parse)

-                        )

-                node = copy.copy(node)

-                if e.tail:

-                    node.tail = (node.tail or "") + e.tail

-                elem[i] = node

-            elif parse == "text":

-                text = loader(href, parse, e.get("encoding"))

-                if text is None:

-                    raise FatalIncludeError(

-                        "cannot load %r as %r" % (href, parse)

-                        )

-                if i:

-                    node = elem[i-1]

-                    node.tail = (node.tail or "") + text + (e.tail or "")

-                else:

-                    elem.text = (elem.text or "") + text + (e.tail or "")

-                del elem[i]

-                continue

-            else:

-                raise FatalIncludeError(

-                    "unknown parse type in xi:include tag (%r)" % parse

-                )

-        elif e.tag == XINCLUDE_FALLBACK:

-            raise FatalIncludeError(

-                "xi:fallback tag must be child of xi:include (%r)" % e.tag

-                )

-        else:

-            include(e, loader)

-        i = i + 1

+#
+# ElementTree
+# $Id: ElementInclude.py 3375 2008-02-13 08:05:08Z fredrik $
+#
+# limited xinclude support for element trees
+#
+# history:
+# 2003-08-15 fl   created
+# 2003-11-14 fl   fixed default loader
+#
+# Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+
+##
+# Limited XInclude support for the ElementTree package.
+##
+
+import copy
+from . import ElementTree
+
+XINCLUDE = "{http://www.w3.org/2001/XInclude}"
+
+XINCLUDE_INCLUDE = XINCLUDE + "include"
+XINCLUDE_FALLBACK = XINCLUDE + "fallback"
+
+##
+# Fatal include error.
+
+class FatalIncludeError(SyntaxError):
+    pass
+
+##
+# Default loader.  This loader reads an included resource from disk.
+#
+# @param href Resource reference.
+# @param parse Parse mode.  Either "xml" or "text".
+# @param encoding Optional text encoding.
+# @return The expanded resource.  If the parse mode is "xml", this
+#    is an ElementTree instance.  If the parse mode is "text", this
+#    is a Unicode string.  If the loader fails, it can return None
+#    or raise an IOError exception.
+# @throws IOError If the loader fails to load the resource.
+
+def default_loader(href, parse, encoding=None):
+    file = open(href)
+    if parse == "xml":
+        data = ElementTree.parse(file).getroot()
+    else:
+        data = file.read()
+        if encoding:
+            data = data.decode(encoding)
+    file.close()
+    return data
+
+##
+# Expand XInclude directives.
+#
+# @param elem Root element.
+# @param loader Optional resource loader.  If omitted, it defaults
+#     to {@link default_loader}.  If given, it should be a callable
+#     that implements the same interface as <b>default_loader</b>.
+# @throws FatalIncludeError If the function fails to include a given
+#     resource, or if the tree contains malformed XInclude elements.
+# @throws IOError If the function fails to load a given resource.
+
+def include(elem, loader=None):
+    if loader is None:
+        loader = default_loader
+    # look for xinclude elements
+    i = 0
+    while i < len(elem):
+        e = elem[i]
+        if e.tag == XINCLUDE_INCLUDE:
+            # process xinclude directive
+            href = e.get("href")
+            parse = e.get("parse", "xml")
+            if parse == "xml":
+                node = loader(href, parse)
+                if node is None:
+                    raise FatalIncludeError(
+                        "cannot load %r as %r" % (href, parse)
+                        )
+                node = copy.copy(node)
+                if e.tail:
+                    node.tail = (node.tail or "") + e.tail
+                elem[i] = node
+            elif parse == "text":
+                text = loader(href, parse, e.get("encoding"))
+                if text is None:
+                    raise FatalIncludeError(
+                        "cannot load %r as %r" % (href, parse)
+                        )
+                if i:
+                    node = elem[i-1]
+                    node.tail = (node.tail or "") + text + (e.tail or "")
+                else:
+                    elem.text = (elem.text or "") + text + (e.tail or "")
+                del elem[i]
+                continue
+            else:
+                raise FatalIncludeError(
+                    "unknown parse type in xi:include tag (%r)" % parse
+                )
+        elif e.tag == XINCLUDE_FALLBACK:
+            raise FatalIncludeError(
+                "xi:fallback tag must be child of xi:include (%r)" % e.tag
+                )
+        else:
+            include(e, loader)
+        i = i + 1
diff --git a/InstallerResources/third_party/etree/ElementPath.py b/InstallerResources/third_party/etree/ElementPath.py
index 5c117c3..4a626d7 100644
--- a/InstallerResources/third_party/etree/ElementPath.py
+++ b/InstallerResources/third_party/etree/ElementPath.py
@@ -1,303 +1,303 @@
-#

-# ElementTree

-# $Id: ElementPath.py 3375 2008-02-13 08:05:08Z fredrik $

-#

-# limited xpath support for element trees

-#

-# history:

-# 2003-05-23 fl   created

-# 2003-05-28 fl   added support for // etc

-# 2003-08-27 fl   fixed parsing of periods in element names

-# 2007-09-10 fl   new selection engine

-# 2007-09-12 fl   fixed parent selector

-# 2007-09-13 fl   added iterfind; changed findall to return a list

-# 2007-11-30 fl   added namespaces support

-# 2009-10-30 fl   added child element value filter

-#

-# Copyright (c) 2003-2009 by Fredrik Lundh.  All rights reserved.

-#

-# fredrik@pythonware.com

-# http://www.pythonware.com

-#

-# --------------------------------------------------------------------

-# The ElementTree toolkit is

-#

-# Copyright (c) 1999-2009 by Fredrik Lundh

-#

-# By obtaining, using, and/or copying this software and/or its

-# associated documentation, you agree that you have read, understood,

-# and will comply with the following terms and conditions:

-#

-# Permission to use, copy, modify, and distribute this software and

-# its associated documentation for any purpose and without fee is

-# hereby granted, provided that the above copyright notice appears in

-# all copies, and that both that copyright notice and this permission

-# notice appear in supporting documentation, and that the name of

-# Secret Labs AB or the author not be used in advertising or publicity

-# pertaining to distribution of the software without specific, written

-# prior permission.

-#

-# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD

-# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-

-# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR

-# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY

-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS

-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE

-# OF THIS SOFTWARE.

-# --------------------------------------------------------------------

-

-# Licensed to PSF under a Contributor Agreement.

-# See http://www.python.org/psf/license for licensing details.

-

-##

-# Implementation module for XPath support.  There's usually no reason

-# to import this module directly; the <b>ElementTree</b> does this for

-# you, if needed.

-##

-

-import re

-

-xpath_tokenizer_re = re.compile(

-    "("

-    "'[^']*'|\"[^\"]*\"|"

-    "::|"

-    "//?|"

-    "\.\.|"

-    "\(\)|"

-    "[/.*:\[\]\(\)@=])|"

-    "((?:\{[^}]+\})?[^/\[\]\(\)@=\s]+)|"

-    "\s+"

-    )

-

-def xpath_tokenizer(pattern, namespaces=None):

-    for token in xpath_tokenizer_re.findall(pattern):

-        tag = token[1]

-        if tag and tag[0] != "{" and ":" in tag:

-            try:

-                prefix, uri = tag.split(":", 1)

-                if not namespaces:

-                    raise KeyError

-                yield token[0], "{%s}%s" % (namespaces[prefix], uri)

-            except KeyError:

-                raise SyntaxError("prefix %r not found in prefix map" % prefix)

-        else:

-            yield token

-

-def get_parent_map(context):

-    parent_map = context.parent_map

-    if parent_map is None:

-        context.parent_map = parent_map = {}

-        for p in context.root.iter():

-            for e in p:

-                parent_map[e] = p

-    return parent_map

-

-def prepare_child(next, token):

-    tag = token[1]

-    def select(context, result):

-        for elem in result:

-            for e in elem:

-                if e.tag == tag:

-                    yield e

-    return select

-

-def prepare_star(next, token):

-    def select(context, result):

-        for elem in result:

-            for e in elem:

-                yield e

-    return select

-

-def prepare_self(next, token):

-    def select(context, result):

-        for elem in result:

-            yield elem

-    return select

-

-def prepare_descendant(next, token):

-    token = next()

-    if token[0] == "*":

-        tag = "*"

-    elif not token[0]:

-        tag = token[1]

-    else:

-        raise SyntaxError("invalid descendant")

-    def select(context, result):

-        for elem in result:

-            for e in elem.iter(tag):

-                if e is not elem:

-                    yield e

-    return select

-

-def prepare_parent(next, token):

-    def select(context, result):

-        # FIXME: raise error if .. is applied at toplevel?

-        parent_map = get_parent_map(context)

-        result_map = {}

-        for elem in result:

-            if elem in parent_map:

-                parent = parent_map[elem]

-                if parent not in result_map:

-                    result_map[parent] = None

-                    yield parent

-    return select

-

-def prepare_predicate(next, token):

-    # FIXME: replace with real parser!!! refs:

-    # http://effbot.org/zone/simple-iterator-parser.htm

-    # http://javascript.crockford.com/tdop/tdop.html

-    signature = []

-    predicate = []

-    while 1:

-        token = next()

-        if token[0] == "]":

-            break

-        if token[0] and token[0][:1] in "'\"":

-            token = "'", token[0][1:-1]

-        signature.append(token[0] or "-")

-        predicate.append(token[1])

-    signature = "".join(signature)

-    # use signature to determine predicate type

-    if signature == "@-":

-        # [@attribute] predicate

-        key = predicate[1]

-        def select(context, result):

-            for elem in result:

-                if elem.get(key) is not None:

-                    yield elem

-        return select

-    if signature == "@-='":

-        # [@attribute='value']

-        key = predicate[1]

-        value = predicate[-1]

-        def select(context, result):

-            for elem in result:

-                if elem.get(key) == value:

-                    yield elem

-        return select

-    if signature == "-" and not re.match("\d+$", predicate[0]):

-        # [tag]

-        tag = predicate[0]

-        def select(context, result):

-            for elem in result:

-                if elem.find(tag) is not None:

-                    yield elem

-        return select

-    if signature == "-='" and not re.match("\d+$", predicate[0]):

-        # [tag='value']

-        tag = predicate[0]

-        value = predicate[-1]

-        def select(context, result):

-            for elem in result:

-                for e in elem.findall(tag):

-                    if "".join(e.itertext()) == value:

-                        yield elem

-                        break

-        return select

-    if signature == "-" or signature == "-()" or signature == "-()-":

-        # [index] or [last()] or [last()-index]

-        if signature == "-":

-            index = int(predicate[0]) - 1

-        else:

-            if predicate[0] != "last":

-                raise SyntaxError("unsupported function")

-            if signature == "-()-":

-                try:

-                    index = int(predicate[2]) - 1

-                except ValueError:

-                    raise SyntaxError("unsupported expression")

-            else:

-                index = -1

-        def select(context, result):

-            parent_map = get_parent_map(context)

-            for elem in result:

-                try:

-                    parent = parent_map[elem]

-                    # FIXME: what if the selector is "*" ?

-                    elems = list(parent.findall(elem.tag))

-                    if elems[index] is elem:

-                        yield elem

-                except (IndexError, KeyError):

-                    pass

-        return select

-    raise SyntaxError("invalid predicate")

-

-ops = {

-    "": prepare_child,

-    "*": prepare_star,

-    ".": prepare_self,

-    "..": prepare_parent,

-    "//": prepare_descendant,

-    "[": prepare_predicate,

-    }

-

-_cache = {}

-

-class _SelectorContext:

-    parent_map = None

-    def __init__(self, root):

-        self.root = root

-

-# --------------------------------------------------------------------

-

-##

-# Generate all matching objects.

-

-def iterfind(elem, path, namespaces=None):

-    # compile selector pattern

-    if path[-1:] == "/":

-        path = path + "*" # implicit all (FIXME: keep this?)

-    try:

-        selector = _cache[path]

-    except KeyError:

-        if len(_cache) > 100:

-            _cache.clear()

-        if path[:1] == "/":

-            raise SyntaxError("cannot use absolute path on element")

-        next = iter(xpath_tokenizer(path, namespaces)).next

-        token = next()

-        selector = []

-        while 1:

-            try:

-                selector.append(ops[token[0]](next, token))

-            except StopIteration:

-                raise SyntaxError("invalid path")

-            try:

-                token = next()

-                if token[0] == "/":

-                    token = next()

-            except StopIteration:

-                break

-        _cache[path] = selector

-    # execute selector pattern

-    result = [elem]

-    context = _SelectorContext(elem)

-    for select in selector:

-        result = select(context, result)

-    return result

-

-##

-# Find first matching object.

-

-def find(elem, path, namespaces=None):

-    try:

-        return iterfind(elem, path, namespaces).next()

-    except StopIteration:

-        return None

-

-##

-# Find all matching objects.

-

-def findall(elem, path, namespaces=None):

-    return list(iterfind(elem, path, namespaces))

-

-##

-# Find text for first matching object.

-

-def findtext(elem, path, default=None, namespaces=None):

-    try:

-        elem = iterfind(elem, path, namespaces).next()

-        return elem.text or ""

-    except StopIteration:

-        return default

+#
+# ElementTree
+# $Id: ElementPath.py 3375 2008-02-13 08:05:08Z fredrik $
+#
+# limited xpath support for element trees
+#
+# history:
+# 2003-05-23 fl   created
+# 2003-05-28 fl   added support for // etc
+# 2003-08-27 fl   fixed parsing of periods in element names
+# 2007-09-10 fl   new selection engine
+# 2007-09-12 fl   fixed parent selector
+# 2007-09-13 fl   added iterfind; changed findall to return a list
+# 2007-11-30 fl   added namespaces support
+# 2009-10-30 fl   added child element value filter
+#
+# Copyright (c) 2003-2009 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2009 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+
+##
+# Implementation module for XPath support.  There's usually no reason
+# to import this module directly; the <b>ElementTree</b> does this for
+# you, if needed.
+##
+
+import re
+
+xpath_tokenizer_re = re.compile(
+    "("
+    "'[^']*'|\"[^\"]*\"|"
+    "::|"
+    "//?|"
+    "\.\.|"
+    "\(\)|"
+    "[/.*:\[\]\(\)@=])|"
+    "((?:\{[^}]+\})?[^/\[\]\(\)@=\s]+)|"
+    "\s+"
+    )
+
+def xpath_tokenizer(pattern, namespaces=None):
+    for token in xpath_tokenizer_re.findall(pattern):
+        tag = token[1]
+        if tag and tag[0] != "{" and ":" in tag:
+            try:
+                prefix, uri = tag.split(":", 1)
+                if not namespaces:
+                    raise KeyError
+                yield token[0], "{%s}%s" % (namespaces[prefix], uri)
+            except KeyError:
+                raise SyntaxError("prefix %r not found in prefix map" % prefix)
+        else:
+            yield token
+
+def get_parent_map(context):
+    parent_map = context.parent_map
+    if parent_map is None:
+        context.parent_map = parent_map = {}
+        for p in context.root.iter():
+            for e in p:
+                parent_map[e] = p
+    return parent_map
+
+def prepare_child(next, token):
+    tag = token[1]
+    def select(context, result):
+        for elem in result:
+            for e in elem:
+                if e.tag == tag:
+                    yield e
+    return select
+
+def prepare_star(next, token):
+    def select(context, result):
+        for elem in result:
+            for e in elem:
+                yield e
+    return select
+
+def prepare_self(next, token):
+    def select(context, result):
+        for elem in result:
+            yield elem
+    return select
+
+def prepare_descendant(next, token):
+    token = next()
+    if token[0] == "*":
+        tag = "*"
+    elif not token[0]:
+        tag = token[1]
+    else:
+        raise SyntaxError("invalid descendant")
+    def select(context, result):
+        for elem in result:
+            for e in elem.iter(tag):
+                if e is not elem:
+                    yield e
+    return select
+
+def prepare_parent(next, token):
+    def select(context, result):
+        # FIXME: raise error if .. is applied at toplevel?
+        parent_map = get_parent_map(context)
+        result_map = {}
+        for elem in result:
+            if elem in parent_map:
+                parent = parent_map[elem]
+                if parent not in result_map:
+                    result_map[parent] = None
+                    yield parent
+    return select
+
+def prepare_predicate(next, token):
+    # FIXME: replace with real parser!!! refs:
+    # http://effbot.org/zone/simple-iterator-parser.htm
+    # http://javascript.crockford.com/tdop/tdop.html
+    signature = []
+    predicate = []
+    while 1:
+        token = next()
+        if token[0] == "]":
+            break
+        if token[0] and token[0][:1] in "'\"":
+            token = "'", token[0][1:-1]
+        signature.append(token[0] or "-")
+        predicate.append(token[1])
+    signature = "".join(signature)
+    # use signature to determine predicate type
+    if signature == "@-":
+        # [@attribute] predicate
+        key = predicate[1]
+        def select(context, result):
+            for elem in result:
+                if elem.get(key) is not None:
+                    yield elem
+        return select
+    if signature == "@-='":
+        # [@attribute='value']
+        key = predicate[1]
+        value = predicate[-1]
+        def select(context, result):
+            for elem in result:
+                if elem.get(key) == value:
+                    yield elem
+        return select
+    if signature == "-" and not re.match("\d+$", predicate[0]):
+        # [tag]
+        tag = predicate[0]
+        def select(context, result):
+            for elem in result:
+                if elem.find(tag) is not None:
+                    yield elem
+        return select
+    if signature == "-='" and not re.match("\d+$", predicate[0]):
+        # [tag='value']
+        tag = predicate[0]
+        value = predicate[-1]
+        def select(context, result):
+            for elem in result:
+                for e in elem.findall(tag):
+                    if "".join(e.itertext()) == value:
+                        yield elem
+                        break
+        return select
+    if signature == "-" or signature == "-()" or signature == "-()-":
+        # [index] or [last()] or [last()-index]
+        if signature == "-":
+            index = int(predicate[0]) - 1
+        else:
+            if predicate[0] != "last":
+                raise SyntaxError("unsupported function")
+            if signature == "-()-":
+                try:
+                    index = int(predicate[2]) - 1
+                except ValueError:
+                    raise SyntaxError("unsupported expression")
+            else:
+                index = -1
+        def select(context, result):
+            parent_map = get_parent_map(context)
+            for elem in result:
+                try:
+                    parent = parent_map[elem]
+                    # FIXME: what if the selector is "*" ?
+                    elems = list(parent.findall(elem.tag))
+                    if elems[index] is elem:
+                        yield elem
+                except (IndexError, KeyError):
+                    pass
+        return select
+    raise SyntaxError("invalid predicate")
+
+ops = {
+    "": prepare_child,
+    "*": prepare_star,
+    ".": prepare_self,
+    "..": prepare_parent,
+    "//": prepare_descendant,
+    "[": prepare_predicate,
+    }
+
+_cache = {}
+
+class _SelectorContext:
+    parent_map = None
+    def __init__(self, root):
+        self.root = root
+
+# --------------------------------------------------------------------
+
+##
+# Generate all matching objects.
+
+def iterfind(elem, path, namespaces=None):
+    # compile selector pattern
+    if path[-1:] == "/":
+        path = path + "*" # implicit all (FIXME: keep this?)
+    try:
+        selector = _cache[path]
+    except KeyError:
+        if len(_cache) > 100:
+            _cache.clear()
+        if path[:1] == "/":
+            raise SyntaxError("cannot use absolute path on element")
+        next = iter(xpath_tokenizer(path, namespaces)).next
+        token = next()
+        selector = []
+        while 1:
+            try:
+                selector.append(ops[token[0]](next, token))
+            except StopIteration:
+                raise SyntaxError("invalid path")
+            try:
+                token = next()
+                if token[0] == "/":
+                    token = next()
+            except StopIteration:
+                break
+        _cache[path] = selector
+    # execute selector pattern
+    result = [elem]
+    context = _SelectorContext(elem)
+    for select in selector:
+        result = select(context, result)
+    return result
+
+##
+# Find first matching object.
+
+def find(elem, path, namespaces=None):
+    try:
+        return iterfind(elem, path, namespaces).next()
+    except StopIteration:
+        return None
+
+##
+# Find all matching objects.
+
+def findall(elem, path, namespaces=None):
+    return list(iterfind(elem, path, namespaces))
+
+##
+# Find text for first matching object.
+
+def findtext(elem, path, default=None, namespaces=None):
+    try:
+        elem = iterfind(elem, path, namespaces).next()
+        return elem.text or ""
+    except StopIteration:
+        return default
diff --git a/InstallerResources/third_party/etree/ElementTree.py b/InstallerResources/third_party/etree/ElementTree.py
index ffbe01e..2b0cf0c 100644
--- a/InstallerResources/third_party/etree/ElementTree.py
+++ b/InstallerResources/third_party/etree/ElementTree.py
@@ -1,1668 +1,1668 @@
-#

-# ElementTree

-# $Id: ElementTree.py 3440 2008-07-18 14:45:01Z fredrik $

-#

-# light-weight XML support for Python 2.3 and later.

-#

-# history (since 1.2.6):

-# 2005-11-12 fl   added tostringlist/fromstringlist helpers

-# 2006-07-05 fl   merged in selected changes from the 1.3 sandbox

-# 2006-07-05 fl   removed support for 2.1 and earlier

-# 2007-06-21 fl   added deprecation/future warnings

-# 2007-08-25 fl   added doctype hook, added parser version attribute etc

-# 2007-08-26 fl   added new serializer code (better namespace handling, etc)

-# 2007-08-27 fl   warn for broken /tag searches on tree level

-# 2007-09-02 fl   added html/text methods to serializer (experimental)

-# 2007-09-05 fl   added method argument to tostring/tostringlist

-# 2007-09-06 fl   improved error handling

-# 2007-09-13 fl   added itertext, iterfind; assorted cleanups

-# 2007-12-15 fl   added C14N hooks, copy method (experimental)

-#

-# Copyright (c) 1999-2008 by Fredrik Lundh.  All rights reserved.

-#

-# fredrik@pythonware.com

-# http://www.pythonware.com

-#

-# --------------------------------------------------------------------

-# The ElementTree toolkit is

-#

-# Copyright (c) 1999-2008 by Fredrik Lundh

-#

-# By obtaining, using, and/or copying this software and/or its

-# associated documentation, you agree that you have read, understood,

-# and will comply with the following terms and conditions:

-#

-# Permission to use, copy, modify, and distribute this software and

-# its associated documentation for any purpose and without fee is

-# hereby granted, provided that the above copyright notice appears in

-# all copies, and that both that copyright notice and this permission

-# notice appear in supporting documentation, and that the name of

-# Secret Labs AB or the author not be used in advertising or publicity

-# pertaining to distribution of the software without specific, written

-# prior permission.

-#

-# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD

-# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-

-# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR

-# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY

-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS

-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE

-# OF THIS SOFTWARE.

-# --------------------------------------------------------------------

-

-# Licensed to PSF under a Contributor Agreement.

-# See http://www.python.org/psf/license for licensing details.

-

-__all__ = [

-    # public symbols

-    "Comment",

-    "dump",

-    "Element", "ElementTree",

-    "fromstring", "fromstringlist",

-    "iselement", "iterparse",

-    "parse", "ParseError",

-    "PI", "ProcessingInstruction",

-    "QName",

-    "SubElement",

-    "tostring", "tostringlist",

-    "TreeBuilder",

-    "VERSION",

-    "XML",

-    "XMLParser", "XMLTreeBuilder",

-    ]

-

-VERSION = "1.3.0"

-

-##

-# The <b>Element</b> type is a flexible container object, designed to

-# store hierarchical data structures in memory. The type can be

-# described as a cross between a list and a dictionary.

-# <p>

-# Each element has a number of properties associated with it:

-# <ul>

-# <li>a <i>tag</i>. This is a string identifying what kind of data

-# this element represents (the element type, in other words).</li>

-# <li>a number of <i>attributes</i>, stored in a Python dictionary.</li>

-# <li>a <i>text</i> string.</li>

-# <li>an optional <i>tail</i> string.</li>

-# <li>a number of <i>child elements</i>, stored in a Python sequence</li>

-# </ul>

-#

-# To create an element instance, use the {@link #Element} constructor

-# or the {@link #SubElement} factory function.

-# <p>

-# The {@link #ElementTree} class can be used to wrap an element

-# structure, and convert it from and to XML.

-##

-

-import sys

-import re

-import warnings

-

-

-class _SimpleElementPath(object):

-    # emulate pre-1.2 find/findtext/findall behaviour

-    def find(self, element, tag, namespaces=None):

-        for elem in element:

-            if elem.tag == tag:

-                return elem

-        return None

-    def findtext(self, element, tag, default=None, namespaces=None):

-        elem = self.find(element, tag)

-        if elem is None:

-            return default

-        return elem.text or ""

-    def iterfind(self, element, tag, namespaces=None):

-        if tag[:3] == ".//":

-            for elem in element.iter(tag[3:]):

-                yield elem

-        for elem in element:

-            if elem.tag == tag:

-                yield elem

-    def findall(self, element, tag, namespaces=None):

-        return list(self.iterfind(element, tag, namespaces))

-

-try:

-    from . import ElementPath

-except ImportError:

-    ElementPath = _SimpleElementPath()

-

-##

-# Parser error.  This is a subclass of <b>SyntaxError</b>.

-# <p>

-# In addition to the exception value, an exception instance contains a

-# specific exception code in the <b>code</b> attribute, and the line and

-# column of the error in the <b>position</b> attribute.

-

-class ParseError(SyntaxError):

-    pass

-

-# --------------------------------------------------------------------

-

-##

-# Checks if an object appears to be a valid element object.

-#

-# @param An element instance.

-# @return A true value if this is an element object.

-# @defreturn flag

-

-def iselement(element):

-    # FIXME: not sure about this; might be a better idea to look

-    # for tag/attrib/text attributes

-    return isinstance(element, Element) or hasattr(element, "tag")

-

-##

-# Element class.  This class defines the Element interface, and

-# provides a reference implementation of this interface.

-# <p>

-# The element name, attribute names, and attribute values can be

-# either ASCII strings (ordinary Python strings containing only 7-bit

-# ASCII characters) or Unicode strings.

-#

-# @param tag The element name.

-# @param attrib An optional dictionary, containing element attributes.

-# @param **extra Additional attributes, given as keyword arguments.

-# @see Element

-# @see SubElement

-# @see Comment

-# @see ProcessingInstruction

-

-class Element(object):

-    # <tag attrib>text<child/>...</tag>tail

-

-    ##

-    # (Attribute) Element tag.

-

-    tag = None

-

-    ##

-    # (Attribute) Element attribute dictionary.  Where possible, use

-    # {@link #Element.get},

-    # {@link #Element.set},

-    # {@link #Element.keys}, and

-    # {@link #Element.items} to access

-    # element attributes.

-

-    attrib = None

-

-    ##

-    # (Attribute) Text before first subelement.  This is either a

-    # string or the value None.  Note that if there was no text, this

-    # attribute may be either None or an empty string, depending on

-    # the parser.

-

-    text = None

-

-    ##

-    # (Attribute) Text after this element's end tag, but before the

-    # next sibling element's start tag.  This is either a string or

-    # the value None.  Note that if there was no text, this attribute

-    # may be either None or an empty string, depending on the parser.

-

-    tail = None # text after end tag, if any

-

-    # constructor

-

-    def __init__(self, tag, attrib={}, **extra):

-        attrib = attrib.copy()

-        attrib.update(extra)

-        self.tag = tag

-        self.attrib = attrib

-        self._children = []

-

-    def __repr__(self):

-        return "<Element %s at 0x%x>" % (repr(self.tag), id(self))

-

-    ##

-    # Creates a new element object of the same type as this element.

-    #

-    # @param tag Element tag.

-    # @param attrib Element attributes, given as a dictionary.

-    # @return A new element instance.

-

-    def makeelement(self, tag, attrib):

-        return self.__class__(tag, attrib)

-

-    ##

-    # (Experimental) Copies the current element.  This creates a

-    # shallow copy; subelements will be shared with the original tree.

-    #

-    # @return A new element instance.

-

-    def copy(self):

-        elem = self.makeelement(self.tag, self.attrib)

-        elem.text = self.text

-        elem.tail = self.tail

-        elem[:] = self

-        return elem

-

-    ##

-    # Returns the number of subelements.  Note that this only counts

-    # full elements; to check if there's any content in an element, you

-    # have to check both the length and the <b>text</b> attribute.

-    #

-    # @return The number of subelements.

-

-    def __len__(self):

-        return len(self._children)

-

-    def __nonzero__(self):

-        warnings.warn(

-            "The behavior of this method will change in future versions.  "

-            "Use specific 'len(elem)' or 'elem is not None' test instead.",

-            FutureWarning, stacklevel=2

-            )

-        return len(self._children) != 0 # emulate old behaviour, for now

-

-    ##

-    # Returns the given subelement, by index.

-    #

-    # @param index What subelement to return.

-    # @return The given subelement.

-    # @exception IndexError If the given element does not exist.

-

-    def __getitem__(self, index):

-        return self._children[index]

-

-    ##

-    # Replaces the given subelement, by index.

-    #

-    # @param index What subelement to replace.

-    # @param element The new element value.

-    # @exception IndexError If the given element does not exist.

-

-    def __setitem__(self, index, element):

-        # if isinstance(index, slice):

-        #     for elt in element:

-        #         assert iselement(elt)

-        # else:

-        #     assert iselement(element)

-        self._children[index] = element

-

-    ##

-    # Deletes the given subelement, by index.

-    #

-    # @param index What subelement to delete.

-    # @exception IndexError If the given element does not exist.

-

-    def __delitem__(self, index):

-        del self._children[index]

-

-    ##

-    # Adds a subelement to the end of this element.  In document order,

-    # the new element will appear after the last existing subelement (or

-    # directly after the text, if it's the first subelement), but before

-    # the end tag for this element.

-    #

-    # @param element The element to add.

-

-    def append(self, element):

-        # assert iselement(element)

-        self._children.append(element)

-

-    ##

-    # Appends subelements from a sequence.

-    #

-    # @param elements A sequence object with zero or more elements.

-    # @since 1.3

-

-    def extend(self, elements):

-        # for element in elements:

-        #     assert iselement(element)

-        self._children.extend(elements)

-

-    ##

-    # Inserts a subelement at the given position in this element.

-    #

-    # @param index Where to insert the new subelement.

-

-    def insert(self, index, element):

-        # assert iselement(element)

-        self._children.insert(index, element)

-

-    ##

-    # Removes a matching subelement.  Unlike the <b>find</b> methods,

-    # this method compares elements based on identity, not on tag

-    # value or contents.  To remove subelements by other means, the

-    # easiest way is often to use a list comprehension to select what

-    # elements to keep, and use slice assignment to update the parent

-    # element.

-    #

-    # @param element What element to remove.

-    # @exception ValueError If a matching element could not be found.

-

-    def remove(self, element):

-        # assert iselement(element)

-        self._children.remove(element)

-

-    ##

-    # (Deprecated) Returns all subelements.  The elements are returned

-    # in document order.

-    #

-    # @return A list of subelements.

-    # @defreturn list of Element instances

-

-    def getchildren(self):

-        warnings.warn(

-            "This method will be removed in future versions.  "

-            "Use 'list(elem)' or iteration over elem instead.",

-            DeprecationWarning, stacklevel=2

-            )

-        return self._children

-

-    ##

-    # Finds the first matching subelement, by tag name or path.

-    #

-    # @param path What element to look for.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return The first matching element, or None if no element was found.

-    # @defreturn Element or None

-

-    def find(self, path, namespaces=None):

-        return ElementPath.find(self, path, namespaces)

-

-    ##

-    # Finds text for the first matching subelement, by tag name or path.

-    #

-    # @param path What element to look for.

-    # @param default What to return if the element was not found.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return The text content of the first matching element, or the

-    #     default value no element was found.  Note that if the element

-    #     is found, but has no text content, this method returns an

-    #     empty string.

-    # @defreturn string

-

-    def findtext(self, path, default=None, namespaces=None):

-        return ElementPath.findtext(self, path, default, namespaces)

-

-    ##

-    # Finds all matching subelements, by tag name or path.

-    #

-    # @param path What element to look for.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return A list or other sequence containing all matching elements,

-    #    in document order.

-    # @defreturn list of Element instances

-

-    def findall(self, path, namespaces=None):

-        return ElementPath.findall(self, path, namespaces)

-

-    ##

-    # Finds all matching subelements, by tag name or path.

-    #

-    # @param path What element to look for.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return An iterator or sequence containing all matching elements,

-    #    in document order.

-    # @defreturn a generated sequence of Element instances

-

-    def iterfind(self, path, namespaces=None):

-        return ElementPath.iterfind(self, path, namespaces)

-

-    ##

-    # Resets an element.  This function removes all subelements, clears

-    # all attributes, and sets the <b>text</b> and <b>tail</b> attributes

-    # to None.

-

-    def clear(self):

-        self.attrib.clear()

-        self._children = []

-        self.text = self.tail = None

-

-    ##

-    # Gets an element attribute.  Equivalent to <b>attrib.get</b>, but

-    # some implementations may handle this a bit more efficiently.

-    #

-    # @param key What attribute to look for.

-    # @param default What to return if the attribute was not found.

-    # @return The attribute value, or the default value, if the

-    #     attribute was not found.

-    # @defreturn string or None

-

-    def get(self, key, default=None):

-        return self.attrib.get(key, default)

-

-    ##

-    # Sets an element attribute.  Equivalent to <b>attrib[key] = value</b>,

-    # but some implementations may handle this a bit more efficiently.

-    #

-    # @param key What attribute to set.

-    # @param value The attribute value.

-

-    def set(self, key, value):

-        self.attrib[key] = value

-

-    ##

-    # Gets a list of attribute names.  The names are returned in an

-    # arbitrary order (just like for an ordinary Python dictionary).

-    # Equivalent to <b>attrib.keys()</b>.

-    #

-    # @return A list of element attribute names.

-    # @defreturn list of strings

-

-    def keys(self):

-        return self.attrib.keys()

-

-    ##

-    # Gets element attributes, as a sequence.  The attributes are

-    # returned in an arbitrary order.  Equivalent to <b>attrib.items()</b>.

-    #

-    # @return A list of (name, value) tuples for all attributes.

-    # @defreturn list of (string, string) tuples

-

-    def items(self):

-        return self.attrib.items()

-

-    ##

-    # Creates a tree iterator.  The iterator loops over this element

-    # and all subelements, in document order, and returns all elements

-    # with a matching tag.

-    # <p>

-    # If the tree structure is modified during iteration, new or removed

-    # elements may or may not be included.  To get a stable set, use the

-    # list() function on the iterator, and loop over the resulting list.

-    #

-    # @param tag What tags to look for (default is to return all elements).

-    # @return An iterator containing all the matching elements.

-    # @defreturn iterator

-

-    def iter(self, tag=None):

-        if tag == "*":

-            tag = None

-        if tag is None or self.tag == tag:

-            yield self

-        for e in self._children:

-            for e in e.iter(tag):

-                yield e

-

-    # compatibility

-    def getiterator(self, tag=None):

-        # Change for a DeprecationWarning in 1.4

-        warnings.warn(

-            "This method will be removed in future versions.  "

-            "Use 'elem.iter()' or 'list(elem.iter())' instead.",

-            PendingDeprecationWarning, stacklevel=2

-        )

-        return list(self.iter(tag))

-

-    ##

-    # Creates a text iterator.  The iterator loops over this element

-    # and all subelements, in document order, and returns all inner

-    # text.

-    #

-    # @return An iterator containing all inner text.

-    # @defreturn iterator

-

-    def itertext(self):

-        tag = self.tag

-        if not isinstance(tag, basestring) and tag is not None:

-            return

-        if self.text:

-            yield self.text

-        for e in self:

-            for s in e.itertext():

-                yield s

-            if e.tail:

-                yield e.tail

-

-# compatibility

-_Element = _ElementInterface = Element

-

-##

-# Subelement factory.  This function creates an element instance, and

-# appends it to an existing element.

-# <p>

-# The element name, attribute names, and attribute values can be

-# either 8-bit ASCII strings or Unicode strings.

-#

-# @param parent The parent element.

-# @param tag The subelement name.

-# @param attrib An optional dictionary, containing element attributes.

-# @param **extra Additional attributes, given as keyword arguments.

-# @return An element instance.

-# @defreturn Element

-

-def SubElement(parent, tag, attrib={}, **extra):

-    attrib = attrib.copy()

-    attrib.update(extra)

-    element = parent.makeelement(tag, attrib)

-    parent.append(element)

-    return element

-

-##

-# Comment element factory.  This factory function creates a special

-# element that will be serialized as an XML comment by the standard

-# serializer.

-# <p>

-# The comment string can be either an 8-bit ASCII string or a Unicode

-# string.

-#

-# @param text A string containing the comment string.

-# @return An element instance, representing a comment.

-# @defreturn Element

-

-def Comment(text=None):

-    element = Element(Comment)

-    element.text = text

-    return element

-

-##

-# PI element factory.  This factory function creates a special element

-# that will be serialized as an XML processing instruction by the standard

-# serializer.

-#

-# @param target A string containing the PI target.

-# @param text A string containing the PI contents, if any.

-# @return An element instance, representing a PI.

-# @defreturn Element

-

-def ProcessingInstruction(target, text=None):

-    element = Element(ProcessingInstruction)

-    element.text = target

-    if text:

-        element.text = element.text + " " + text

-    return element

-

-PI = ProcessingInstruction

-

-##

-# QName wrapper.  This can be used to wrap a QName attribute value, in

-# order to get proper namespace handling on output.

-#

-# @param text A string containing the QName value, in the form {uri}local,

-#     or, if the tag argument is given, the URI part of a QName.

-# @param tag Optional tag.  If given, the first argument is interpreted as

-#     an URI, and this argument is interpreted as a local name.

-# @return An opaque object, representing the QName.

-

-class QName(object):

-    def __init__(self, text_or_uri, tag=None):

-        if tag:

-            text_or_uri = "{%s}%s" % (text_or_uri, tag)

-        self.text = text_or_uri

-    def __str__(self):

-        return self.text

-    def __hash__(self):

-        return hash(self.text)

-    def __cmp__(self, other):

-        if isinstance(other, QName):

-            return cmp(self.text, other.text)

-        return cmp(self.text, other)

-

-# --------------------------------------------------------------------

-

-##

-# ElementTree wrapper class.  This class represents an entire element

-# hierarchy, and adds some extra support for serialization to and from

-# standard XML.

-#

-# @param element Optional root element.

-# @keyparam file Optional file handle or file name.  If given, the

-#     tree is initialized with the contents of this XML file.

-

-class ElementTree(object):

-

-    def __init__(self, element=None, file=None):

-        # assert element is None or iselement(element)

-        self._root = element # first node

-        if file:

-            self.parse(file)

-

-    ##

-    # Gets the root element for this tree.

-    #

-    # @return An element instance.

-    # @defreturn Element

-

-    def getroot(self):

-        return self._root

-

-    ##

-    # Replaces the root element for this tree.  This discards the

-    # current contents of the tree, and replaces it with the given

-    # element.  Use with care.

-    #

-    # @param element An element instance.

-

-    def _setroot(self, element):

-        # assert iselement(element)

-        self._root = element

-

-    ##

-    # Loads an external XML document into this element tree.

-    #

-    # @param source A file name or file object.  If a file object is

-    #     given, it only has to implement a <b>read(n)</b> method.

-    # @keyparam parser An optional parser instance.  If not given, the

-    #     standard {@link XMLParser} parser is used.

-    # @return The document root element.

-    # @defreturn Element

-    # @exception ParseError If the parser fails to parse the document.

-

-    def parse(self, source, parser=None):

-        close_source = False

-        if not hasattr(source, "read"):

-            source = open(source, "rb")

-            close_source = True

-        try:

-            if not parser:

-                parser = XMLParser(target=TreeBuilder())

-            while 1:

-                data = source.read(65536)

-                if not data:

-                    break

-                parser.feed(data)

-            self._root = parser.close()

-            return self._root

-        finally:

-            if close_source:

-                source.close()

-

-    ##

-    # Creates a tree iterator for the root element.  The iterator loops

-    # over all elements in this tree, in document order.

-    #

-    # @param tag What tags to look for (default is to return all elements)

-    # @return An iterator.

-    # @defreturn iterator

-

-    def iter(self, tag=None):

-        # assert self._root is not None

-        return self._root.iter(tag)

-

-    # compatibility

-    def getiterator(self, tag=None):

-        # Change for a DeprecationWarning in 1.4

-        warnings.warn(

-            "This method will be removed in future versions.  "

-            "Use 'tree.iter()' or 'list(tree.iter())' instead.",

-            PendingDeprecationWarning, stacklevel=2

-        )

-        return list(self.iter(tag))

-

-    ##

-    # Finds the first toplevel element with given tag.

-    # Same as getroot().find(path).

-    #

-    # @param path What element to look for.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return The first matching element, or None if no element was found.

-    # @defreturn Element or None

-

-    def find(self, path, namespaces=None):

-        # assert self._root is not None

-        if path[:1] == "/":

-            path = "." + path

-            warnings.warn(

-                "This search is broken in 1.3 and earlier, and will be "

-                "fixed in a future version.  If you rely on the current "

-                "behaviour, change it to %r" % path,

-                FutureWarning, stacklevel=2

-                )

-        return self._root.find(path, namespaces)

-

-    ##

-    # Finds the element text for the first toplevel element with given

-    # tag.  Same as getroot().findtext(path).

-    #

-    # @param path What toplevel element to look for.

-    # @param default What to return if the element was not found.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return The text content of the first matching element, or the

-    #     default value no element was found.  Note that if the element

-    #     is found, but has no text content, this method returns an

-    #     empty string.

-    # @defreturn string

-

-    def findtext(self, path, default=None, namespaces=None):

-        # assert self._root is not None

-        if path[:1] == "/":

-            path = "." + path

-            warnings.warn(

-                "This search is broken in 1.3 and earlier, and will be "

-                "fixed in a future version.  If you rely on the current "

-                "behaviour, change it to %r" % path,

-                FutureWarning, stacklevel=2

-                )

-        return self._root.findtext(path, default, namespaces)

-

-    ##

-    # Finds all toplevel elements with the given tag.

-    # Same as getroot().findall(path).

-    #

-    # @param path What element to look for.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return A list or iterator containing all matching elements,

-    #    in document order.

-    # @defreturn list of Element instances

-

-    def findall(self, path, namespaces=None):

-        # assert self._root is not None

-        if path[:1] == "/":

-            path = "." + path

-            warnings.warn(

-                "This search is broken in 1.3 and earlier, and will be "

-                "fixed in a future version.  If you rely on the current "

-                "behaviour, change it to %r" % path,

-                FutureWarning, stacklevel=2

-                )

-        return self._root.findall(path, namespaces)

-

-    ##

-    # Finds all matching subelements, by tag name or path.

-    # Same as getroot().iterfind(path).

-    #

-    # @param path What element to look for.

-    # @keyparam namespaces Optional namespace prefix map.

-    # @return An iterator or sequence containing all matching elements,

-    #    in document order.

-    # @defreturn a generated sequence of Element instances

-

-    def iterfind(self, path, namespaces=None):

-        # assert self._root is not None

-        if path[:1] == "/":

-            path = "." + path

-            warnings.warn(

-                "This search is broken in 1.3 and earlier, and will be "

-                "fixed in a future version.  If you rely on the current "

-                "behaviour, change it to %r" % path,

-                FutureWarning, stacklevel=2

-                )

-        return self._root.iterfind(path, namespaces)

-

-    ##

-    # Writes the element tree to a file, as XML.

-    #

-    # @def write(file, **options)

-    # @param file A file name, or a file object opened for writing.

-    # @param **options Options, given as keyword arguments.

-    # @keyparam encoding Optional output encoding (default is US-ASCII).

-    # @keyparam method Optional output method ("xml", "html", "text" or

-    #     "c14n"; default is "xml").

-    # @keyparam xml_declaration Controls if an XML declaration should

-    #     be added to the file.  Use False for never, True for always,

-    #     None for only if not US-ASCII or UTF-8.  None is default.

-

-    def write(self, file_or_filename,

-              # keyword arguments

-              encoding=None,

-              xml_declaration=None,

-              default_namespace=None,

-              method=None):

-        # assert self._root is not None

-        if not method:

-            method = "xml"

-        elif method not in _serialize:

-            # FIXME: raise an ImportError for c14n if ElementC14N is missing?

-            raise ValueError("unknown method %r" % method)

-        if hasattr(file_or_filename, "write"):

-            file = file_or_filename

-        else:

-            file = open(file_or_filename, "wb")

-        write = file.write

-        if not encoding:

-            if method == "c14n":

-                encoding = "utf-8"

-            else:

-                encoding = "us-ascii"

-        elif xml_declaration or (xml_declaration is None and

-                                 encoding not in ("utf-8", "us-ascii")):

-            if method == "xml":

-                write("<?xml version='1.0' encoding='%s'?>\n" % encoding)

-        if method == "text":

-            _serialize_text(write, self._root, encoding)

-        else:

-            qnames, namespaces = _namespaces(

-                self._root, encoding, default_namespace

-                )

-            serialize = _serialize[method]

-            serialize(write, self._root, encoding, qnames, namespaces)

-        if file_or_filename is not file:

-            file.close()

-

-    def write_c14n(self, file):

-        # lxml.etree compatibility.  use output method instead

-        return self.write(file, method="c14n")

-

-# --------------------------------------------------------------------

-# serialization support

-

-def _namespaces(elem, encoding, default_namespace=None):

-    # identify namespaces used in this tree

-

-    # maps qnames to *encoded* prefix:local names

-    qnames = {None: None}

-

-    # maps uri:s to prefixes

-    namespaces = {}

-    if default_namespace:

-        namespaces[default_namespace] = ""

-

-    def encode(text):

-        return text.encode(encoding)

-

-    def add_qname(qname):

-        # calculate serialized qname representation

-        try:

-            if qname[:1] == "{":

-                uri, tag = qname[1:].rsplit("}", 1)

-                prefix = namespaces.get(uri)

-                if prefix is None:

-                    prefix = _namespace_map.get(uri)

-                    if prefix is None:

-                        prefix = "ns%d" % len(namespaces)

-                    if prefix != "xml":

-                        namespaces[uri] = prefix

-                if prefix:

-                    qnames[qname] = encode("%s:%s" % (prefix, tag))

-                else:

-                    qnames[qname] = encode(tag) # default element

-            else:

-                if default_namespace:

-                    # FIXME: can this be handled in XML 1.0?

-                    raise ValueError(

-                        "cannot use non-qualified names with "

-                        "default_namespace option"

-                        )

-                qnames[qname] = encode(qname)

-        except TypeError:

-            _raise_serialization_error(qname)

-

-    # populate qname and namespaces table

-    try:

-        iterate = elem.iter

-    except AttributeError:

-        iterate = elem.getiterator # cET compatibility

-    for elem in iterate():

-        tag = elem.tag

-        if isinstance(tag, QName):

-            if tag.text not in qnames:

-                add_qname(tag.text)

-        elif isinstance(tag, basestring):

-            if tag not in qnames:

-                add_qname(tag)

-        elif tag is not None and tag is not Comment and tag is not PI:

-            _raise_serialization_error(tag)

-        for key, value in elem.items():

-            if isinstance(key, QName):

-                key = key.text

-            if key not in qnames:

-                add_qname(key)

-            if isinstance(value, QName) and value.text not in qnames:

-                add_qname(value.text)

-        text = elem.text

-        if isinstance(text, QName) and text.text not in qnames:

-            add_qname(text.text)

-    return qnames, namespaces

-

-def _serialize_xml(write, elem, encoding, qnames, namespaces):

-    tag = elem.tag

-    text = elem.text

-    if tag is Comment:

-        write("<!--%s-->" % _encode(text, encoding))

-    elif tag is ProcessingInstruction:

-        write("<?%s?>" % _encode(text, encoding))

-    else:

-        tag = qnames[tag]

-        if tag is None:

-            if text:

-                write(_escape_cdata(text, encoding))

-            for e in elem:

-                _serialize_xml(write, e, encoding, qnames, None)

-        else:

-            write("<" + tag)

-            items = elem.items()

-            if items or namespaces:

-                if namespaces:

-                    for v, k in sorted(namespaces.items(),

-                                       key=lambda x: x[1]):  # sort on prefix

-                        if k:

-                            k = ":" + k

-                        write(" xmlns%s=\"%s\"" % (

-                            k.encode(encoding),

-                            _escape_attrib(v, encoding)

-                            ))

-                for k, v in sorted(items):  # lexical order

-                    if isinstance(k, QName):

-                        k = k.text

-                    if isinstance(v, QName):

-                        v = qnames[v.text]

-                    else:

-                        v = _escape_attrib(v, encoding)

-                    write(" %s=\"%s\"" % (qnames[k], v))

-            if text or len(elem):

-                write(">")

-                if text:

-                    write(_escape_cdata(text, encoding))

-                for e in elem:

-                    _serialize_xml(write, e, encoding, qnames, None)

-                write("</" + tag + ">")

-            else:

-                write(" />")

-    if elem.tail:

-        write(_escape_cdata(elem.tail, encoding))

-

-HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",

-              "img", "input", "isindex", "link", "meta" "param")

-

-try:

-    HTML_EMPTY = set(HTML_EMPTY)

-except NameError:

-    pass

-

-def _serialize_html(write, elem, encoding, qnames, namespaces):

-    tag = elem.tag

-    text = elem.text

-    if tag is Comment:

-        write("<!--%s-->" % _escape_cdata(text, encoding))

-    elif tag is ProcessingInstruction:

-        write("<?%s?>" % _escape_cdata(text, encoding))

-    else:

-        tag = qnames[tag]

-        if tag is None:

-            if text:

-                write(_escape_cdata(text, encoding))

-            for e in elem:

-                _serialize_html(write, e, encoding, qnames, None)

-        else:

-            write("<" + tag)

-            items = elem.items()

-            if items or namespaces:

-                if namespaces:

-                    for v, k in sorted(namespaces.items(),

-                                       key=lambda x: x[1]):  # sort on prefix

-                        if k:

-                            k = ":" + k

-                        write(" xmlns%s=\"%s\"" % (

-                            k.encode(encoding),

-                            _escape_attrib(v, encoding)

-                            ))

-                for k, v in sorted(items):  # lexical order

-                    if isinstance(k, QName):

-                        k = k.text

-                    if isinstance(v, QName):

-                        v = qnames[v.text]

-                    else:

-                        v = _escape_attrib_html(v, encoding)

-                    # FIXME: handle boolean attributes

-                    write(" %s=\"%s\"" % (qnames[k], v))

-            write(">")

-            tag = tag.lower()

-            if text:

-                if tag == "script" or tag == "style":

-                    write(_encode(text, encoding))

-                else:

-                    write(_escape_cdata(text, encoding))

-            for e in elem:

-                _serialize_html(write, e, encoding, qnames, None)

-            if tag not in HTML_EMPTY:

-                write("</" + tag + ">")

-    if elem.tail:

-        write(_escape_cdata(elem.tail, encoding))

-

-def _serialize_text(write, elem, encoding):

-    for part in elem.itertext():

-        write(part.encode(encoding))

-    if elem.tail:

-        write(elem.tail.encode(encoding))

-

-_serialize = {

-    "xml": _serialize_xml,

-    "html": _serialize_html,

-    "text": _serialize_text,

-# this optional method is imported at the end of the module

-#   "c14n": _serialize_c14n,

-}

-

-##

-# Registers a namespace prefix.  The registry is global, and any

-# existing mapping for either the given prefix or the namespace URI

-# will be removed.

-#

-# @param prefix Namespace prefix.

-# @param uri Namespace uri.  Tags and attributes in this namespace

-#     will be serialized with the given prefix, if at all possible.

-# @exception ValueError If the prefix is reserved, or is otherwise

-#     invalid.

-

-def register_namespace(prefix, uri):

-    if re.match("ns\d+$", prefix):

-        raise ValueError("Prefix format reserved for internal use")

-    for k, v in _namespace_map.items():

-        if k == uri or v == prefix:

-            del _namespace_map[k]

-    _namespace_map[uri] = prefix

-

-_namespace_map = {

-    # "well-known" namespace prefixes

-    "http://www.w3.org/XML/1998/namespace": "xml",

-    "http://www.w3.org/1999/xhtml": "html",

-    "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",

-    "http://schemas.xmlsoap.org/wsdl/": "wsdl",

-    # xml schema

-    "http://www.w3.org/2001/XMLSchema": "xs",

-    "http://www.w3.org/2001/XMLSchema-instance": "xsi",

-    # dublin core

-    "http://purl.org/dc/elements/1.1/": "dc",

-}

-

-def _raise_serialization_error(text):

-    raise TypeError(

-        "cannot serialize %r (type %s)" % (text, type(text).__name__)

-        )

-

-def _encode(text, encoding):

-    try:

-        return text.encode(encoding, "xmlcharrefreplace")

-    except (TypeError, AttributeError):

-        _raise_serialization_error(text)

-

-def _escape_cdata(text, encoding):

-    # escape character data

-    try:

-        # it's worth avoiding do-nothing calls for strings that are

-        # shorter than 500 character, or so.  assume that's, by far,

-        # the most common case in most applications.

-        if "&" in text:

-            text = text.replace("&", "&amp;")

-        if "<" in text:

-            text = text.replace("<", "&lt;")

-        if ">" in text:

-            text = text.replace(">", "&gt;")

-        return text.encode(encoding, "xmlcharrefreplace")

-    except (TypeError, AttributeError):

-        _raise_serialization_error(text)

-

-def _escape_attrib(text, encoding):

-    # escape attribute value

-    try:

-        if "&" in text:

-            text = text.replace("&", "&amp;")

-        if "<" in text:

-            text = text.replace("<", "&lt;")

-        if ">" in text:

-            text = text.replace(">", "&gt;")

-        if "\"" in text:

-            text = text.replace("\"", "&quot;")

-        if "\n" in text:

-            text = text.replace("\n", "&#10;")

-        return text.encode(encoding, "xmlcharrefreplace")

-    except (TypeError, AttributeError):

-        _raise_serialization_error(text)

-

-def _escape_attrib_html(text, encoding):

-    # escape attribute value

-    try:

-        if "&" in text:

-            text = text.replace("&", "&amp;")

-        if ">" in text:

-            text = text.replace(">", "&gt;")

-        if "\"" in text:

-            text = text.replace("\"", "&quot;")

-        return text.encode(encoding, "xmlcharrefreplace")

-    except (TypeError, AttributeError):

-        _raise_serialization_error(text)

-

-# --------------------------------------------------------------------

-

-##

-# Generates a string representation of an XML element, including all

-# subelements.

-#

-# @param element An Element instance.

-# @keyparam encoding Optional output encoding (default is US-ASCII).

-# @keyparam method Optional output method ("xml", "html", "text" or

-#     "c14n"; default is "xml").

-# @return An encoded string containing the XML data.

-# @defreturn string

-

-def tostring(element, encoding=None, method=None):

-    class dummy:

-        pass

-    data = []

-    file = dummy()

-    file.write = data.append

-    ElementTree(element).write(file, encoding, method=method)

-    return "".join(data)

-

-##

-# Generates a string representation of an XML element, including all

-# subelements.  The string is returned as a sequence of string fragments.

-#

-# @param element An Element instance.

-# @keyparam encoding Optional output encoding (default is US-ASCII).

-# @keyparam method Optional output method ("xml", "html", "text" or

-#     "c14n"; default is "xml").

-# @return A sequence object containing the XML data.

-# @defreturn sequence

-# @since 1.3

-

-def tostringlist(element, encoding=None, method=None):

-    class dummy:

-        pass

-    data = []

-    file = dummy()

-    file.write = data.append

-    ElementTree(element).write(file, encoding, method=method)

-    # FIXME: merge small fragments into larger parts

-    return data

-

-##

-# Writes an element tree or element structure to sys.stdout.  This

-# function should be used for debugging only.

-# <p>

-# The exact output format is implementation dependent.  In this

-# version, it's written as an ordinary XML file.

-#

-# @param elem An element tree or an individual element.

-

-def dump(elem):

-    # debugging

-    if not isinstance(elem, ElementTree):

-        elem = ElementTree(elem)

-    elem.write(sys.stdout)

-    tail = elem.getroot().tail

-    if not tail or tail[-1] != "\n":

-        sys.stdout.write("\n")

-

-# --------------------------------------------------------------------

-# parsing

-

-##

-# Parses an XML document into an element tree.

-#

-# @param source A filename or file object containing XML data.

-# @param parser An optional parser instance.  If not given, the

-#     standard {@link XMLParser} parser is used.

-# @return An ElementTree instance

-

-def parse(source, parser=None):

-    tree = ElementTree()

-    tree.parse(source, parser)

-    return tree

-

-##

-# Parses an XML document into an element tree incrementally, and reports

-# what's going on to the user.

-#

-# @param source A filename or file object containing XML data.

-# @param events A list of events to report back.  If omitted, only "end"

-#     events are reported.

-# @param parser An optional parser instance.  If not given, the

-#     standard {@link XMLParser} parser is used.

-# @return A (event, elem) iterator.

-

-def iterparse(source, events=None, parser=None):

-    close_source = False

-    if not hasattr(source, "read"):

-        source = open(source, "rb")

-        close_source = True

-    if not parser:

-        parser = XMLParser(target=TreeBuilder())

-    return _IterParseIterator(source, events, parser, close_source)

-

-class _IterParseIterator(object):

-

-    def __init__(self, source, events, parser, close_source=False):

-        self._file = source

-        self._close_file = close_source

-        self._events = []

-        self._index = 0

-        self._error = None

-        self.root = self._root = None

-        self._parser = parser

-        # wire up the parser for event reporting

-        parser = self._parser._parser

-        append = self._events.append

-        if events is None:

-            events = ["end"]

-        for event in events:

-            if event == "start":

-                try:

-                    parser.ordered_attributes = 1

-                    parser.specified_attributes = 1

-                    def handler(tag, attrib_in, event=event, append=append,

-                                start=self._parser._start_list):

-                        append((event, start(tag, attrib_in)))

-                    parser.StartElementHandler = handler

-                except AttributeError:

-                    def handler(tag, attrib_in, event=event, append=append,

-                                start=self._parser._start):

-                        append((event, start(tag, attrib_in)))

-                    parser.StartElementHandler = handler

-            elif event == "end":

-                def handler(tag, event=event, append=append,

-                            end=self._parser._end):

-                    append((event, end(tag)))

-                parser.EndElementHandler = handler

-            elif event == "start-ns":

-                def handler(prefix, uri, event=event, append=append):

-                    try:

-                        uri = (uri or "").encode("ascii")

-                    except UnicodeError:

-                        pass

-                    append((event, (prefix or "", uri or "")))

-                parser.StartNamespaceDeclHandler = handler

-            elif event == "end-ns":

-                def handler(prefix, event=event, append=append):

-                    append((event, None))

-                parser.EndNamespaceDeclHandler = handler

-            else:

-                raise ValueError("unknown event %r" % event)

-

-    def next(self):

-        while 1:

-            try:

-                item = self._events[self._index]

-                self._index += 1

-                return item

-            except IndexError:

-                pass

-            if self._error:

-                e = self._error

-                self._error = None

-                raise e

-            if self._parser is None:

-                self.root = self._root

-                if self._close_file:

-                    self._file.close()

-                raise StopIteration

-            # load event buffer

-            del self._events[:]

-            self._index = 0

-            data = self._file.read(16384)

-            if data:

-                try:

-                    self._parser.feed(data)

-                except SyntaxError as exc:

-                    self._error = exc

-            else:

-                self._root = self._parser.close()

-                self._parser = None

-

-    def __iter__(self):

-        return self

-

-##

-# Parses an XML document from a string constant.  This function can

-# be used to embed "XML literals" in Python code.

-#

-# @param source A string containing XML data.

-# @param parser An optional parser instance.  If not given, the

-#     standard {@link XMLParser} parser is used.

-# @return An Element instance.

-# @defreturn Element

-

-def XML(text, parser=None):

-    if not parser:

-        parser = XMLParser(target=TreeBuilder())

-    parser.feed(text)

-    return parser.close()

-

-##

-# Parses an XML document from a string constant, and also returns

-# a dictionary which maps from element id:s to elements.

-#

-# @param source A string containing XML data.

-# @param parser An optional parser instance.  If not given, the

-#     standard {@link XMLParser} parser is used.

-# @return A tuple containing an Element instance and a dictionary.

-# @defreturn (Element, dictionary)

-

-def XMLID(text, parser=None):

-    if not parser:

-        parser = XMLParser(target=TreeBuilder())

-    parser.feed(text)

-    tree = parser.close()

-    ids = {}

-    for elem in tree.iter():

-        id = elem.get("id")

-        if id:

-            ids[id] = elem

-    return tree, ids

-

-##

-# Parses an XML document from a string constant.  Same as {@link #XML}.

-#

-# @def fromstring(text)

-# @param source A string containing XML data.

-# @return An Element instance.

-# @defreturn Element

-

-fromstring = XML

-

-##

-# Parses an XML document from a sequence of string fragments.

-#

-# @param sequence A list or other sequence containing XML data fragments.

-# @param parser An optional parser instance.  If not given, the

-#     standard {@link XMLParser} parser is used.

-# @return An Element instance.

-# @defreturn Element

-# @since 1.3

-

-def fromstringlist(sequence, parser=None):

-    if not parser:

-        parser = XMLParser(target=TreeBuilder())

-    for text in sequence:

-        parser.feed(text)

-    return parser.close()

-

-# --------------------------------------------------------------------

-

-##

-# Generic element structure builder.  This builder converts a sequence

-# of {@link #TreeBuilder.start}, {@link #TreeBuilder.data}, and {@link

-# #TreeBuilder.end} method calls to a well-formed element structure.

-# <p>

-# You can use this class to build an element structure using a custom XML

-# parser, or a parser for some other XML-like format.

-#

-# @param element_factory Optional element factory.  This factory

-#    is called to create new Element instances, as necessary.

-

-class TreeBuilder(object):

-

-    def __init__(self, element_factory=None):

-        self._data = [] # data collector

-        self._elem = [] # element stack

-        self._last = None # last element

-        self._tail = None # true if we're after an end tag

-        if element_factory is None:

-            element_factory = Element

-        self._factory = element_factory

-

-    ##

-    # Flushes the builder buffers, and returns the toplevel document

-    # element.

-    #

-    # @return An Element instance.

-    # @defreturn Element

-

-    def close(self):

-        assert len(self._elem) == 0, "missing end tags"

-        assert self._last is not None, "missing toplevel element"

-        return self._last

-

-    def _flush(self):

-        if self._data:

-            if self._last is not None:

-                text = "".join(self._data)

-                if self._tail:

-                    assert self._last.tail is None, "internal error (tail)"

-                    self._last.tail = text

-                else:

-                    assert self._last.text is None, "internal error (text)"

-                    self._last.text = text

-            self._data = []

-

-    ##

-    # Adds text to the current element.

-    #

-    # @param data A string.  This should be either an 8-bit string

-    #    containing ASCII text, or a Unicode string.

-

-    def data(self, data):

-        self._data.append(data)

-

-    ##

-    # Opens a new element.

-    #

-    # @param tag The element name.

-    # @param attrib A dictionary containing element attributes.

-    # @return The opened element.

-    # @defreturn Element

-

-    def start(self, tag, attrs):

-        self._flush()

-        self._last = elem = self._factory(tag, attrs)

-        if self._elem:

-            self._elem[-1].append(elem)

-        self._elem.append(elem)

-        self._tail = 0

-        return elem

-

-    ##

-    # Closes the current element.

-    #

-    # @param tag The element name.

-    # @return The closed element.

-    # @defreturn Element

-

-    def end(self, tag):

-        self._flush()

-        self._last = self._elem.pop()

-        assert self._last.tag == tag,\

-               "end tag mismatch (expected %s, got %s)" % (

-                   self._last.tag, tag)

-        self._tail = 1

-        return self._last

-

-##

-# Element structure builder for XML source data, based on the

-# <b>expat</b> parser.

-#

-# @keyparam target Target object.  If omitted, the builder uses an

-#     instance of the standard {@link #TreeBuilder} class.

-# @keyparam html Predefine HTML entities.  This flag is not supported

-#     by the current implementation.

-# @keyparam encoding Optional encoding.  If given, the value overrides

-#     the encoding specified in the XML file.

-# @see #ElementTree

-# @see #TreeBuilder

-

-class XMLParser(object):

-

-    def __init__(self, html=0, target=None, encoding=None):

-        try:

-            from xml.parsers import expat

-        except ImportError:

-            try:

-                import pyexpat as expat

-            except ImportError:

-                raise ImportError(

-                    "No module named expat; use SimpleXMLTreeBuilder instead"

-                    )

-        parser = expat.ParserCreate(encoding, "}")

-        if target is None:

-            target = TreeBuilder()

-        # underscored names are provided for compatibility only

-        self.parser = self._parser = parser

-        self.target = self._target = target

-        self._error = expat.error

-        self._names = {} # name memo cache

-        # callbacks

-        parser.DefaultHandlerExpand = self._default

-        parser.StartElementHandler = self._start

-        parser.EndElementHandler = self._end

-        parser.CharacterDataHandler = self._data

-        # optional callbacks

-        parser.CommentHandler = self._comment

-        parser.ProcessingInstructionHandler = self._pi

-        # let expat do the buffering, if supported

-        try:

-            self._parser.buffer_text = 1

-        except AttributeError:

-            pass

-        # use new-style attribute handling, if supported

-        try:

-            self._parser.ordered_attributes = 1

-            self._parser.specified_attributes = 1

-            parser.StartElementHandler = self._start_list

-        except AttributeError:

-            pass

-        self._doctype = None

-        self.entity = {}

-        try:

-            self.version = "Expat %d.%d.%d" % expat.version_info

-        except AttributeError:

-            pass # unknown

-

-    def _raiseerror(self, value):

-        err = ParseError(value)

-        err.code = value.code

-        err.position = value.lineno, value.offset

-        raise err

-

-    def _fixtext(self, text):

-        # convert text string to ascii, if possible

-        try:

-            return text.encode("ascii")

-        except UnicodeError:

-            return text

-

-    def _fixname(self, key):

-        # expand qname, and convert name string to ascii, if possible

-        try:

-            name = self._names[key]

-        except KeyError:

-            name = key

-            if "}" in name:

-                name = "{" + name

-            self._names[key] = name = self._fixtext(name)

-        return name

-

-    def _start(self, tag, attrib_in):

-        fixname = self._fixname

-        fixtext = self._fixtext

-        tag = fixname(tag)

-        attrib = {}

-        for key, value in attrib_in.items():

-            attrib[fixname(key)] = fixtext(value)

-        return self.target.start(tag, attrib)

-

-    def _start_list(self, tag, attrib_in):

-        fixname = self._fixname

-        fixtext = self._fixtext

-        tag = fixname(tag)

-        attrib = {}

-        if attrib_in:

-            for i in range(0, len(attrib_in), 2):

-                attrib[fixname(attrib_in[i])] = fixtext(attrib_in[i+1])

-        return self.target.start(tag, attrib)

-

-    def _data(self, text):

-        return self.target.data(self._fixtext(text))

-

-    def _end(self, tag):

-        return self.target.end(self._fixname(tag))

-

-    def _comment(self, data):

-        try:

-            comment = self.target.comment

-        except AttributeError:

-            pass

-        else:

-            return comment(self._fixtext(data))

-

-    def _pi(self, target, data):

-        try:

-            pi = self.target.pi

-        except AttributeError:

-            pass

-        else:

-            return pi(self._fixtext(target), self._fixtext(data))

-

-    def _default(self, text):

-        prefix = text[:1]

-        if prefix == "&":

-            # deal with undefined entities

-            try:

-                self.target.data(self.entity[text[1:-1]])

-            except KeyError:

-                from xml.parsers import expat

-                err = expat.error(

-                    "undefined entity %s: line %d, column %d" %

-                    (text, self._parser.ErrorLineNumber,

-                    self._parser.ErrorColumnNumber)

-                    )

-                err.code = 11 # XML_ERROR_UNDEFINED_ENTITY

-                err.lineno = self._parser.ErrorLineNumber

-                err.offset = self._parser.ErrorColumnNumber

-                raise err

-        elif prefix == "<" and text[:9] == "<!DOCTYPE":

-            self._doctype = [] # inside a doctype declaration

-        elif self._doctype is not None:

-            # parse doctype contents

-            if prefix == ">":

-                self._doctype = None

-                return

-            text = text.strip()

-            if not text:

-                return

-            self._doctype.append(text)

-            n = len(self._doctype)

-            if n > 2:

-                type = self._doctype[1]

-                if type == "PUBLIC" and n == 4:

-                    name, type, pubid, system = self._doctype

-                elif type == "SYSTEM" and n == 3:

-                    name, type, system = self._doctype

-                    pubid = None

-                else:

-                    return

-                if pubid:

-                    pubid = pubid[1:-1]

-                if hasattr(self.target, "doctype"):

-                    self.target.doctype(name, pubid, system[1:-1])

-                elif self.doctype is not self._XMLParser__doctype:

-                    # warn about deprecated call

-                    self._XMLParser__doctype(name, pubid, system[1:-1])

-                    self.doctype(name, pubid, system[1:-1])

-                self._doctype = None

-

-    ##

-    # (Deprecated) Handles a doctype declaration.

-    #

-    # @param name Doctype name.

-    # @param pubid Public identifier.

-    # @param system System identifier.

-

-    def doctype(self, name, pubid, system):

-        """This method of XMLParser is deprecated."""

-        warnings.warn(

-            "This method of XMLParser is deprecated.  Define doctype() "

-            "method on the TreeBuilder target.",

-            DeprecationWarning,

-            )

-

-    # sentinel, if doctype is redefined in a subclass

-    __doctype = doctype

-

-    ##

-    # Feeds data to the parser.

-    #

-    # @param data Encoded data.

-

-    def feed(self, data):

-        try:

-            self._parser.Parse(data, 0)

-        except self._error, v:

-            self._raiseerror(v)

-

-    ##

-    # Finishes feeding data to the parser.

-    #

-    # @return An element structure.

-    # @defreturn Element

-

-    def close(self):

-        try:

-            self._parser.Parse("", 1) # end of data

-        except self._error, v:

-            self._raiseerror(v)

-        tree = self.target.close()

-        del self.target, self._parser # get rid of circular references

-        return tree

-

-# compatibility

-XMLTreeBuilder = XMLParser

-

-# workaround circular import.

-try:

-    from ElementC14N import _serialize_c14n

-    _serialize["c14n"] = _serialize_c14n

-except ImportError:

-    pass

+#
+# ElementTree
+# $Id: ElementTree.py 3440 2008-07-18 14:45:01Z fredrik $
+#
+# light-weight XML support for Python 2.3 and later.
+#
+# history (since 1.2.6):
+# 2005-11-12 fl   added tostringlist/fromstringlist helpers
+# 2006-07-05 fl   merged in selected changes from the 1.3 sandbox
+# 2006-07-05 fl   removed support for 2.1 and earlier
+# 2007-06-21 fl   added deprecation/future warnings
+# 2007-08-25 fl   added doctype hook, added parser version attribute etc
+# 2007-08-26 fl   added new serializer code (better namespace handling, etc)
+# 2007-08-27 fl   warn for broken /tag searches on tree level
+# 2007-09-02 fl   added html/text methods to serializer (experimental)
+# 2007-09-05 fl   added method argument to tostring/tostringlist
+# 2007-09-06 fl   improved error handling
+# 2007-09-13 fl   added itertext, iterfind; assorted cleanups
+# 2007-12-15 fl   added C14N hooks, copy method (experimental)
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
+
+__all__ = [
+    # public symbols
+    "Comment",
+    "dump",
+    "Element", "ElementTree",
+    "fromstring", "fromstringlist",
+    "iselement", "iterparse",
+    "parse", "ParseError",
+    "PI", "ProcessingInstruction",
+    "QName",
+    "SubElement",
+    "tostring", "tostringlist",
+    "TreeBuilder",
+    "VERSION",
+    "XML",
+    "XMLParser", "XMLTreeBuilder",
+    ]
+
+VERSION = "1.3.0"
+
+##
+# The <b>Element</b> type is a flexible container object, designed to
+# store hierarchical data structures in memory. The type can be
+# described as a cross between a list and a dictionary.
+# <p>
+# Each element has a number of properties associated with it:
+# <ul>
+# <li>a <i>tag</i>. This is a string identifying what kind of data
+# this element represents (the element type, in other words).</li>
+# <li>a number of <i>attributes</i>, stored in a Python dictionary.</li>
+# <li>a <i>text</i> string.</li>
+# <li>an optional <i>tail</i> string.</li>
+# <li>a number of <i>child elements</i>, stored in a Python sequence</li>
+# </ul>
+#
+# To create an element instance, use the {@link #Element} constructor
+# or the {@link #SubElement} factory function.
+# <p>
+# The {@link #ElementTree} class can be used to wrap an element
+# structure, and convert it from and to XML.
+##
+
+import sys
+import re
+import warnings
+
+
+class _SimpleElementPath(object):
+    # emulate pre-1.2 find/findtext/findall behaviour
+    def find(self, element, tag, namespaces=None):
+        for elem in element:
+            if elem.tag == tag:
+                return elem
+        return None
+    def findtext(self, element, tag, default=None, namespaces=None):
+        elem = self.find(element, tag)
+        if elem is None:
+            return default
+        return elem.text or ""
+    def iterfind(self, element, tag, namespaces=None):
+        if tag[:3] == ".//":
+            for elem in element.iter(tag[3:]):
+                yield elem
+        for elem in element:
+            if elem.tag == tag:
+                yield elem
+    def findall(self, element, tag, namespaces=None):
+        return list(self.iterfind(element, tag, namespaces))
+
+try:
+    from . import ElementPath
+except ImportError:
+    ElementPath = _SimpleElementPath()
+
+##
+# Parser error.  This is a subclass of <b>SyntaxError</b>.
+# <p>
+# In addition to the exception value, an exception instance contains a
+# specific exception code in the <b>code</b> attribute, and the line and
+# column of the error in the <b>position</b> attribute.
+
+class ParseError(SyntaxError):
+    pass
+
+# --------------------------------------------------------------------
+
+##
+# Checks if an object appears to be a valid element object.
+#
+# @param An element instance.
+# @return A true value if this is an element object.
+# @defreturn flag
+
+def iselement(element):
+    # FIXME: not sure about this; might be a better idea to look
+    # for tag/attrib/text attributes
+    return isinstance(element, Element) or hasattr(element, "tag")
+
+##
+# Element class.  This class defines the Element interface, and
+# provides a reference implementation of this interface.
+# <p>
+# The element name, attribute names, and attribute values can be
+# either ASCII strings (ordinary Python strings containing only 7-bit
+# ASCII characters) or Unicode strings.
+#
+# @param tag The element name.
+# @param attrib An optional dictionary, containing element attributes.
+# @param **extra Additional attributes, given as keyword arguments.
+# @see Element
+# @see SubElement
+# @see Comment
+# @see ProcessingInstruction
+
+class Element(object):
+    # <tag attrib>text<child/>...</tag>tail
+
+    ##
+    # (Attribute) Element tag.
+
+    tag = None
+
+    ##
+    # (Attribute) Element attribute dictionary.  Where possible, use
+    # {@link #Element.get},
+    # {@link #Element.set},
+    # {@link #Element.keys}, and
+    # {@link #Element.items} to access
+    # element attributes.
+
+    attrib = None
+
+    ##
+    # (Attribute) Text before first subelement.  This is either a
+    # string or the value None.  Note that if there was no text, this
+    # attribute may be either None or an empty string, depending on
+    # the parser.
+
+    text = None
+
+    ##
+    # (Attribute) Text after this element's end tag, but before the
+    # next sibling element's start tag.  This is either a string or
+    # the value None.  Note that if there was no text, this attribute
+    # may be either None or an empty string, depending on the parser.
+
+    tail = None # text after end tag, if any
+
+    # constructor
+
+    def __init__(self, tag, attrib={}, **extra):
+        attrib = attrib.copy()
+        attrib.update(extra)
+        self.tag = tag
+        self.attrib = attrib
+        self._children = []
+
+    def __repr__(self):
+        return "<Element %s at 0x%x>" % (repr(self.tag), id(self))
+
+    ##
+    # Creates a new element object of the same type as this element.
+    #
+    # @param tag Element tag.
+    # @param attrib Element attributes, given as a dictionary.
+    # @return A new element instance.
+
+    def makeelement(self, tag, attrib):
+        return self.__class__(tag, attrib)
+
+    ##
+    # (Experimental) Copies the current element.  This creates a
+    # shallow copy; subelements will be shared with the original tree.
+    #
+    # @return A new element instance.
+
+    def copy(self):
+        elem = self.makeelement(self.tag, self.attrib)
+        elem.text = self.text
+        elem.tail = self.tail
+        elem[:] = self
+        return elem
+
+    ##
+    # Returns the number of subelements.  Note that this only counts
+    # full elements; to check if there's any content in an element, you
+    # have to check both the length and the <b>text</b> attribute.
+    #
+    # @return The number of subelements.
+
+    def __len__(self):
+        return len(self._children)
+
+    def __nonzero__(self):
+        warnings.warn(
+            "The behavior of this method will change in future versions.  "
+            "Use specific 'len(elem)' or 'elem is not None' test instead.",
+            FutureWarning, stacklevel=2
+            )
+        return len(self._children) != 0 # emulate old behaviour, for now
+
+    ##
+    # Returns the given subelement, by index.
+    #
+    # @param index What subelement to return.
+    # @return The given subelement.
+    # @exception IndexError If the given element does not exist.
+
+    def __getitem__(self, index):
+        return self._children[index]
+
+    ##
+    # Replaces the given subelement, by index.
+    #
+    # @param index What subelement to replace.
+    # @param element The new element value.
+    # @exception IndexError If the given element does not exist.
+
+    def __setitem__(self, index, element):
+        # if isinstance(index, slice):
+        #     for elt in element:
+        #         assert iselement(elt)
+        # else:
+        #     assert iselement(element)
+        self._children[index] = element
+
+    ##
+    # Deletes the given subelement, by index.
+    #
+    # @param index What subelement to delete.
+    # @exception IndexError If the given element does not exist.
+
+    def __delitem__(self, index):
+        del self._children[index]
+
+    ##
+    # Adds a subelement to the end of this element.  In document order,
+    # the new element will appear after the last existing subelement (or
+    # directly after the text, if it's the first subelement), but before
+    # the end tag for this element.
+    #
+    # @param element The element to add.
+
+    def append(self, element):
+        # assert iselement(element)
+        self._children.append(element)
+
+    ##
+    # Appends subelements from a sequence.
+    #
+    # @param elements A sequence object with zero or more elements.
+    # @since 1.3
+
+    def extend(self, elements):
+        # for element in elements:
+        #     assert iselement(element)
+        self._children.extend(elements)
+
+    ##
+    # Inserts a subelement at the given position in this element.
+    #
+    # @param index Where to insert the new subelement.
+
+    def insert(self, index, element):
+        # assert iselement(element)
+        self._children.insert(index, element)
+
+    ##
+    # Removes a matching subelement.  Unlike the <b>find</b> methods,
+    # this method compares elements based on identity, not on tag
+    # value or contents.  To remove subelements by other means, the
+    # easiest way is often to use a list comprehension to select what
+    # elements to keep, and use slice assignment to update the parent
+    # element.
+    #
+    # @param element What element to remove.
+    # @exception ValueError If a matching element could not be found.
+
+    def remove(self, element):
+        # assert iselement(element)
+        self._children.remove(element)
+
+    ##
+    # (Deprecated) Returns all subelements.  The elements are returned
+    # in document order.
+    #
+    # @return A list of subelements.
+    # @defreturn list of Element instances
+
+    def getchildren(self):
+        warnings.warn(
+            "This method will be removed in future versions.  "
+            "Use 'list(elem)' or iteration over elem instead.",
+            DeprecationWarning, stacklevel=2
+            )
+        return self._children
+
+    ##
+    # Finds the first matching subelement, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The first matching element, or None if no element was found.
+    # @defreturn Element or None
+
+    def find(self, path, namespaces=None):
+        return ElementPath.find(self, path, namespaces)
+
+    ##
+    # Finds text for the first matching subelement, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @param default What to return if the element was not found.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The text content of the first matching element, or the
+    #     default value no element was found.  Note that if the element
+    #     is found, but has no text content, this method returns an
+    #     empty string.
+    # @defreturn string
+
+    def findtext(self, path, default=None, namespaces=None):
+        return ElementPath.findtext(self, path, default, namespaces)
+
+    ##
+    # Finds all matching subelements, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return A list or other sequence containing all matching elements,
+    #    in document order.
+    # @defreturn list of Element instances
+
+    def findall(self, path, namespaces=None):
+        return ElementPath.findall(self, path, namespaces)
+
+    ##
+    # Finds all matching subelements, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return An iterator or sequence containing all matching elements,
+    #    in document order.
+    # @defreturn a generated sequence of Element instances
+
+    def iterfind(self, path, namespaces=None):
+        return ElementPath.iterfind(self, path, namespaces)
+
+    ##
+    # Resets an element.  This function removes all subelements, clears
+    # all attributes, and sets the <b>text</b> and <b>tail</b> attributes
+    # to None.
+
+    def clear(self):
+        self.attrib.clear()
+        self._children = []
+        self.text = self.tail = None
+
+    ##
+    # Gets an element attribute.  Equivalent to <b>attrib.get</b>, but
+    # some implementations may handle this a bit more efficiently.
+    #
+    # @param key What attribute to look for.
+    # @param default What to return if the attribute was not found.
+    # @return The attribute value, or the default value, if the
+    #     attribute was not found.
+    # @defreturn string or None
+
+    def get(self, key, default=None):
+        return self.attrib.get(key, default)
+
+    ##
+    # Sets an element attribute.  Equivalent to <b>attrib[key] = value</b>,
+    # but some implementations may handle this a bit more efficiently.
+    #
+    # @param key What attribute to set.
+    # @param value The attribute value.
+
+    def set(self, key, value):
+        self.attrib[key] = value
+
+    ##
+    # Gets a list of attribute names.  The names are returned in an
+    # arbitrary order (just like for an ordinary Python dictionary).
+    # Equivalent to <b>attrib.keys()</b>.
+    #
+    # @return A list of element attribute names.
+    # @defreturn list of strings
+
+    def keys(self):
+        return self.attrib.keys()
+
+    ##
+    # Gets element attributes, as a sequence.  The attributes are
+    # returned in an arbitrary order.  Equivalent to <b>attrib.items()</b>.
+    #
+    # @return A list of (name, value) tuples for all attributes.
+    # @defreturn list of (string, string) tuples
+
+    def items(self):
+        return self.attrib.items()
+
+    ##
+    # Creates a tree iterator.  The iterator loops over this element
+    # and all subelements, in document order, and returns all elements
+    # with a matching tag.
+    # <p>
+    # If the tree structure is modified during iteration, new or removed
+    # elements may or may not be included.  To get a stable set, use the
+    # list() function on the iterator, and loop over the resulting list.
+    #
+    # @param tag What tags to look for (default is to return all elements).
+    # @return An iterator containing all the matching elements.
+    # @defreturn iterator
+
+    def iter(self, tag=None):
+        if tag == "*":
+            tag = None
+        if tag is None or self.tag == tag:
+            yield self
+        for e in self._children:
+            for e in e.iter(tag):
+                yield e
+
+    # compatibility
+    def getiterator(self, tag=None):
+        # Change for a DeprecationWarning in 1.4
+        warnings.warn(
+            "This method will be removed in future versions.  "
+            "Use 'elem.iter()' or 'list(elem.iter())' instead.",
+            PendingDeprecationWarning, stacklevel=2
+        )
+        return list(self.iter(tag))
+
+    ##
+    # Creates a text iterator.  The iterator loops over this element
+    # and all subelements, in document order, and returns all inner
+    # text.
+    #
+    # @return An iterator containing all inner text.
+    # @defreturn iterator
+
+    def itertext(self):
+        tag = self.tag
+        if not isinstance(tag, basestring) and tag is not None:
+            return
+        if self.text:
+            yield self.text
+        for e in self:
+            for s in e.itertext():
+                yield s
+            if e.tail:
+                yield e.tail
+
+# compatibility
+_Element = _ElementInterface = Element
+
+##
+# Subelement factory.  This function creates an element instance, and
+# appends it to an existing element.
+# <p>
+# The element name, attribute names, and attribute values can be
+# either 8-bit ASCII strings or Unicode strings.
+#
+# @param parent The parent element.
+# @param tag The subelement name.
+# @param attrib An optional dictionary, containing element attributes.
+# @param **extra Additional attributes, given as keyword arguments.
+# @return An element instance.
+# @defreturn Element
+
+def SubElement(parent, tag, attrib={}, **extra):
+    attrib = attrib.copy()
+    attrib.update(extra)
+    element = parent.makeelement(tag, attrib)
+    parent.append(element)
+    return element
+
+##
+# Comment element factory.  This factory function creates a special
+# element that will be serialized as an XML comment by the standard
+# serializer.
+# <p>
+# The comment string can be either an 8-bit ASCII string or a Unicode
+# string.
+#
+# @param text A string containing the comment string.
+# @return An element instance, representing a comment.
+# @defreturn Element
+
+def Comment(text=None):
+    element = Element(Comment)
+    element.text = text
+    return element
+
+##
+# PI element factory.  This factory function creates a special element
+# that will be serialized as an XML processing instruction by the standard
+# serializer.
+#
+# @param target A string containing the PI target.
+# @param text A string containing the PI contents, if any.
+# @return An element instance, representing a PI.
+# @defreturn Element
+
+def ProcessingInstruction(target, text=None):
+    element = Element(ProcessingInstruction)
+    element.text = target
+    if text:
+        element.text = element.text + " " + text
+    return element
+
+PI = ProcessingInstruction
+
+##
+# QName wrapper.  This can be used to wrap a QName attribute value, in
+# order to get proper namespace handling on output.
+#
+# @param text A string containing the QName value, in the form {uri}local,
+#     or, if the tag argument is given, the URI part of a QName.
+# @param tag Optional tag.  If given, the first argument is interpreted as
+#     an URI, and this argument is interpreted as a local name.
+# @return An opaque object, representing the QName.
+
+class QName(object):
+    def __init__(self, text_or_uri, tag=None):
+        if tag:
+            text_or_uri = "{%s}%s" % (text_or_uri, tag)
+        self.text = text_or_uri
+    def __str__(self):
+        return self.text
+    def __hash__(self):
+        return hash(self.text)
+    def __cmp__(self, other):
+        if isinstance(other, QName):
+            return cmp(self.text, other.text)
+        return cmp(self.text, other)
+
+# --------------------------------------------------------------------
+
+##
+# ElementTree wrapper class.  This class represents an entire element
+# hierarchy, and adds some extra support for serialization to and from
+# standard XML.
+#
+# @param element Optional root element.
+# @keyparam file Optional file handle or file name.  If given, the
+#     tree is initialized with the contents of this XML file.
+
+class ElementTree(object):
+
+    def __init__(self, element=None, file=None):
+        # assert element is None or iselement(element)
+        self._root = element # first node
+        if file:
+            self.parse(file)
+
+    ##
+    # Gets the root element for this tree.
+    #
+    # @return An element instance.
+    # @defreturn Element
+
+    def getroot(self):
+        return self._root
+
+    ##
+    # Replaces the root element for this tree.  This discards the
+    # current contents of the tree, and replaces it with the given
+    # element.  Use with care.
+    #
+    # @param element An element instance.
+
+    def _setroot(self, element):
+        # assert iselement(element)
+        self._root = element
+
+    ##
+    # Loads an external XML document into this element tree.
+    #
+    # @param source A file name or file object.  If a file object is
+    #     given, it only has to implement a <b>read(n)</b> method.
+    # @keyparam parser An optional parser instance.  If not given, the
+    #     standard {@link XMLParser} parser is used.
+    # @return The document root element.
+    # @defreturn Element
+    # @exception ParseError If the parser fails to parse the document.
+
+    def parse(self, source, parser=None):
+        close_source = False
+        if not hasattr(source, "read"):
+            source = open(source, "rb")
+            close_source = True
+        try:
+            if not parser:
+                parser = XMLParser(target=TreeBuilder())
+            while 1:
+                data = source.read(65536)
+                if not data:
+                    break
+                parser.feed(data)
+            self._root = parser.close()
+            return self._root
+        finally:
+            if close_source:
+                source.close()
+
+    ##
+    # Creates a tree iterator for the root element.  The iterator loops
+    # over all elements in this tree, in document order.
+    #
+    # @param tag What tags to look for (default is to return all elements)
+    # @return An iterator.
+    # @defreturn iterator
+
+    def iter(self, tag=None):
+        # assert self._root is not None
+        return self._root.iter(tag)
+
+    # compatibility
+    def getiterator(self, tag=None):
+        # Change for a DeprecationWarning in 1.4
+        warnings.warn(
+            "This method will be removed in future versions.  "
+            "Use 'tree.iter()' or 'list(tree.iter())' instead.",
+            PendingDeprecationWarning, stacklevel=2
+        )
+        return list(self.iter(tag))
+
+    ##
+    # Finds the first toplevel element with given tag.
+    # Same as getroot().find(path).
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The first matching element, or None if no element was found.
+    # @defreturn Element or None
+
+    def find(self, path, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.find(path, namespaces)
+
+    ##
+    # Finds the element text for the first toplevel element with given
+    # tag.  Same as getroot().findtext(path).
+    #
+    # @param path What toplevel element to look for.
+    # @param default What to return if the element was not found.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return The text content of the first matching element, or the
+    #     default value no element was found.  Note that if the element
+    #     is found, but has no text content, this method returns an
+    #     empty string.
+    # @defreturn string
+
+    def findtext(self, path, default=None, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.findtext(path, default, namespaces)
+
+    ##
+    # Finds all toplevel elements with the given tag.
+    # Same as getroot().findall(path).
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return A list or iterator containing all matching elements,
+    #    in document order.
+    # @defreturn list of Element instances
+
+    def findall(self, path, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.findall(path, namespaces)
+
+    ##
+    # Finds all matching subelements, by tag name or path.
+    # Same as getroot().iterfind(path).
+    #
+    # @param path What element to look for.
+    # @keyparam namespaces Optional namespace prefix map.
+    # @return An iterator or sequence containing all matching elements,
+    #    in document order.
+    # @defreturn a generated sequence of Element instances
+
+    def iterfind(self, path, namespaces=None):
+        # assert self._root is not None
+        if path[:1] == "/":
+            path = "." + path
+            warnings.warn(
+                "This search is broken in 1.3 and earlier, and will be "
+                "fixed in a future version.  If you rely on the current "
+                "behaviour, change it to %r" % path,
+                FutureWarning, stacklevel=2
+                )
+        return self._root.iterfind(path, namespaces)
+
+    ##
+    # Writes the element tree to a file, as XML.
+    #
+    # @def write(file, **options)
+    # @param file A file name, or a file object opened for writing.
+    # @param **options Options, given as keyword arguments.
+    # @keyparam encoding Optional output encoding (default is US-ASCII).
+    # @keyparam method Optional output method ("xml", "html", "text" or
+    #     "c14n"; default is "xml").
+    # @keyparam xml_declaration Controls if an XML declaration should
+    #     be added to the file.  Use False for never, True for always,
+    #     None for only if not US-ASCII or UTF-8.  None is default.
+
+    def write(self, file_or_filename,
+              # keyword arguments
+              encoding=None,
+              xml_declaration=None,
+              default_namespace=None,
+              method=None):
+        # assert self._root is not None
+        if not method:
+            method = "xml"
+        elif method not in _serialize:
+            # FIXME: raise an ImportError for c14n if ElementC14N is missing?
+            raise ValueError("unknown method %r" % method)
+        if hasattr(file_or_filename, "write"):
+            file = file_or_filename
+        else:
+            file = open(file_or_filename, "wb")
+        write = file.write
+        if not encoding:
+            if method == "c14n":
+                encoding = "utf-8"
+            else:
+                encoding = "us-ascii"
+        elif xml_declaration or (xml_declaration is None and
+                                 encoding not in ("utf-8", "us-ascii")):
+            if method == "xml":
+                write("<?xml version='1.0' encoding='%s'?>\n" % encoding)
+        if method == "text":
+            _serialize_text(write, self._root, encoding)
+        else:
+            qnames, namespaces = _namespaces(
+                self._root, encoding, default_namespace
+                )
+            serialize = _serialize[method]
+            serialize(write, self._root, encoding, qnames, namespaces)
+        if file_or_filename is not file:
+            file.close()
+
+    def write_c14n(self, file):
+        # lxml.etree compatibility.  use output method instead
+        return self.write(file, method="c14n")
+
+# --------------------------------------------------------------------
+# serialization support
+
+def _namespaces(elem, encoding, default_namespace=None):
+    # identify namespaces used in this tree
+
+    # maps qnames to *encoded* prefix:local names
+    qnames = {None: None}
+
+    # maps uri:s to prefixes
+    namespaces = {}
+    if default_namespace:
+        namespaces[default_namespace] = ""
+
+    def encode(text):
+        return text.encode(encoding)
+
+    def add_qname(qname):
+        # calculate serialized qname representation
+        try:
+            if qname[:1] == "{":
+                uri, tag = qname[1:].rsplit("}", 1)
+                prefix = namespaces.get(uri)
+                if prefix is None:
+                    prefix = _namespace_map.get(uri)
+                    if prefix is None:
+                        prefix = "ns%d" % len(namespaces)
+                    if prefix != "xml":
+                        namespaces[uri] = prefix
+                if prefix:
+                    qnames[qname] = encode("%s:%s" % (prefix, tag))
+                else:
+                    qnames[qname] = encode(tag) # default element
+            else:
+                if default_namespace:
+                    # FIXME: can this be handled in XML 1.0?
+                    raise ValueError(
+                        "cannot use non-qualified names with "
+                        "default_namespace option"
+                        )
+                qnames[qname] = encode(qname)
+        except TypeError:
+            _raise_serialization_error(qname)
+
+    # populate qname and namespaces table
+    try:
+        iterate = elem.iter
+    except AttributeError:
+        iterate = elem.getiterator # cET compatibility
+    for elem in iterate():
+        tag = elem.tag
+        if isinstance(tag, QName):
+            if tag.text not in qnames:
+                add_qname(tag.text)
+        elif isinstance(tag, basestring):
+            if tag not in qnames:
+                add_qname(tag)
+        elif tag is not None and tag is not Comment and tag is not PI:
+            _raise_serialization_error(tag)
+        for key, value in elem.items():
+            if isinstance(key, QName):
+                key = key.text
+            if key not in qnames:
+                add_qname(key)
+            if isinstance(value, QName) and value.text not in qnames:
+                add_qname(value.text)
+        text = elem.text
+        if isinstance(text, QName) and text.text not in qnames:
+            add_qname(text.text)
+    return qnames, namespaces
+
+def _serialize_xml(write, elem, encoding, qnames, namespaces):
+    tag = elem.tag
+    text = elem.text
+    if tag is Comment:
+        write("<!--%s-->" % _encode(text, encoding))
+    elif tag is ProcessingInstruction:
+        write("<?%s?>" % _encode(text, encoding))
+    else:
+        tag = qnames[tag]
+        if tag is None:
+            if text:
+                write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_xml(write, e, encoding, qnames, None)
+        else:
+            write("<" + tag)
+            items = elem.items()
+            if items or namespaces:
+                if namespaces:
+                    for v, k in sorted(namespaces.items(),
+                                       key=lambda x: x[1]):  # sort on prefix
+                        if k:
+                            k = ":" + k
+                        write(" xmlns%s=\"%s\"" % (
+                            k.encode(encoding),
+                            _escape_attrib(v, encoding)
+                            ))
+                for k, v in sorted(items):  # lexical order
+                    if isinstance(k, QName):
+                        k = k.text
+                    if isinstance(v, QName):
+                        v = qnames[v.text]
+                    else:
+                        v = _escape_attrib(v, encoding)
+                    write(" %s=\"%s\"" % (qnames[k], v))
+            if text or len(elem):
+                write(">")
+                if text:
+                    write(_escape_cdata(text, encoding))
+                for e in elem:
+                    _serialize_xml(write, e, encoding, qnames, None)
+                write("</" + tag + ">")
+            else:
+                write(" />")
+    if elem.tail:
+        write(_escape_cdata(elem.tail, encoding))
+
+HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
+              "img", "input", "isindex", "link", "meta" "param")
+
+try:
+    HTML_EMPTY = set(HTML_EMPTY)
+except NameError:
+    pass
+
+def _serialize_html(write, elem, encoding, qnames, namespaces):
+    tag = elem.tag
+    text = elem.text
+    if tag is Comment:
+        write("<!--%s-->" % _escape_cdata(text, encoding))
+    elif tag is ProcessingInstruction:
+        write("<?%s?>" % _escape_cdata(text, encoding))
+    else:
+        tag = qnames[tag]
+        if tag is None:
+            if text:
+                write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_html(write, e, encoding, qnames, None)
+        else:
+            write("<" + tag)
+            items = elem.items()
+            if items or namespaces:
+                if namespaces:
+                    for v, k in sorted(namespaces.items(),
+                                       key=lambda x: x[1]):  # sort on prefix
+                        if k:
+                            k = ":" + k
+                        write(" xmlns%s=\"%s\"" % (
+                            k.encode(encoding),
+                            _escape_attrib(v, encoding)
+                            ))
+                for k, v in sorted(items):  # lexical order
+                    if isinstance(k, QName):
+                        k = k.text
+                    if isinstance(v, QName):
+                        v = qnames[v.text]
+                    else:
+                        v = _escape_attrib_html(v, encoding)
+                    # FIXME: handle boolean attributes
+                    write(" %s=\"%s\"" % (qnames[k], v))
+            write(">")
+            tag = tag.lower()
+            if text:
+                if tag == "script" or tag == "style":
+                    write(_encode(text, encoding))
+                else:
+                    write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_html(write, e, encoding, qnames, None)
+            if tag not in HTML_EMPTY:
+                write("</" + tag + ">")
+    if elem.tail:
+        write(_escape_cdata(elem.tail, encoding))
+
+def _serialize_text(write, elem, encoding):
+    for part in elem.itertext():
+        write(part.encode(encoding))
+    if elem.tail:
+        write(elem.tail.encode(encoding))
+
+_serialize = {
+    "xml": _serialize_xml,
+    "html": _serialize_html,
+    "text": _serialize_text,
+# this optional method is imported at the end of the module
+#   "c14n": _serialize_c14n,
+}
+
+##
+# Registers a namespace prefix.  The registry is global, and any
+# existing mapping for either the given prefix or the namespace URI
+# will be removed.
+#
+# @param prefix Namespace prefix.
+# @param uri Namespace uri.  Tags and attributes in this namespace
+#     will be serialized with the given prefix, if at all possible.
+# @exception ValueError If the prefix is reserved, or is otherwise
+#     invalid.
+
+def register_namespace(prefix, uri):
+    if re.match("ns\d+$", prefix):
+        raise ValueError("Prefix format reserved for internal use")
+    for k, v in _namespace_map.items():
+        if k == uri or v == prefix:
+            del _namespace_map[k]
+    _namespace_map[uri] = prefix
+
+_namespace_map = {
+    # "well-known" namespace prefixes
+    "http://www.w3.org/XML/1998/namespace": "xml",
+    "http://www.w3.org/1999/xhtml": "html",
+    "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
+    "http://schemas.xmlsoap.org/wsdl/": "wsdl",
+    # xml schema
+    "http://www.w3.org/2001/XMLSchema": "xs",
+    "http://www.w3.org/2001/XMLSchema-instance": "xsi",
+    # dublin core
+    "http://purl.org/dc/elements/1.1/": "dc",
+}
+
+def _raise_serialization_error(text):
+    raise TypeError(
+        "cannot serialize %r (type %s)" % (text, type(text).__name__)
+        )
+
+def _encode(text, encoding):
+    try:
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_cdata(text, encoding):
+    # escape character data
+    try:
+        # it's worth avoiding do-nothing calls for strings that are
+        # shorter than 500 character, or so.  assume that's, by far,
+        # the most common case in most applications.
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if "<" in text:
+            text = text.replace("<", "&lt;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_attrib(text, encoding):
+    # escape attribute value
+    try:
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if "<" in text:
+            text = text.replace("<", "&lt;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        if "\"" in text:
+            text = text.replace("\"", "&quot;")
+        if "\n" in text:
+            text = text.replace("\n", "&#10;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_attrib_html(text, encoding):
+    # escape attribute value
+    try:
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        if "\"" in text:
+            text = text.replace("\"", "&quot;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+# --------------------------------------------------------------------
+
+##
+# Generates a string representation of an XML element, including all
+# subelements.
+#
+# @param element An Element instance.
+# @keyparam encoding Optional output encoding (default is US-ASCII).
+# @keyparam method Optional output method ("xml", "html", "text" or
+#     "c14n"; default is "xml").
+# @return An encoded string containing the XML data.
+# @defreturn string
+
+def tostring(element, encoding=None, method=None):
+    class dummy:
+        pass
+    data = []
+    file = dummy()
+    file.write = data.append
+    ElementTree(element).write(file, encoding, method=method)
+    return "".join(data)
+
+##
+# Generates a string representation of an XML element, including all
+# subelements.  The string is returned as a sequence of string fragments.
+#
+# @param element An Element instance.
+# @keyparam encoding Optional output encoding (default is US-ASCII).
+# @keyparam method Optional output method ("xml", "html", "text" or
+#     "c14n"; default is "xml").
+# @return A sequence object containing the XML data.
+# @defreturn sequence
+# @since 1.3
+
+def tostringlist(element, encoding=None, method=None):
+    class dummy:
+        pass
+    data = []
+    file = dummy()
+    file.write = data.append
+    ElementTree(element).write(file, encoding, method=method)
+    # FIXME: merge small fragments into larger parts
+    return data
+
+##
+# Writes an element tree or element structure to sys.stdout.  This
+# function should be used for debugging only.
+# <p>
+# The exact output format is implementation dependent.  In this
+# version, it's written as an ordinary XML file.
+#
+# @param elem An element tree or an individual element.
+
+def dump(elem):
+    # debugging
+    if not isinstance(elem, ElementTree):
+        elem = ElementTree(elem)
+    elem.write(sys.stdout)
+    tail = elem.getroot().tail
+    if not tail or tail[-1] != "\n":
+        sys.stdout.write("\n")
+
+# --------------------------------------------------------------------
+# parsing
+
+##
+# Parses an XML document into an element tree.
+#
+# @param source A filename or file object containing XML data.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return An ElementTree instance
+
+def parse(source, parser=None):
+    tree = ElementTree()
+    tree.parse(source, parser)
+    return tree
+
+##
+# Parses an XML document into an element tree incrementally, and reports
+# what's going on to the user.
+#
+# @param source A filename or file object containing XML data.
+# @param events A list of events to report back.  If omitted, only "end"
+#     events are reported.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return A (event, elem) iterator.
+
+def iterparse(source, events=None, parser=None):
+    close_source = False
+    if not hasattr(source, "read"):
+        source = open(source, "rb")
+        close_source = True
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    return _IterParseIterator(source, events, parser, close_source)
+
+class _IterParseIterator(object):
+
+    def __init__(self, source, events, parser, close_source=False):
+        self._file = source
+        self._close_file = close_source
+        self._events = []
+        self._index = 0
+        self._error = None
+        self.root = self._root = None
+        self._parser = parser
+        # wire up the parser for event reporting
+        parser = self._parser._parser
+        append = self._events.append
+        if events is None:
+            events = ["end"]
+        for event in events:
+            if event == "start":
+                try:
+                    parser.ordered_attributes = 1
+                    parser.specified_attributes = 1
+                    def handler(tag, attrib_in, event=event, append=append,
+                                start=self._parser._start_list):
+                        append((event, start(tag, attrib_in)))
+                    parser.StartElementHandler = handler
+                except AttributeError:
+                    def handler(tag, attrib_in, event=event, append=append,
+                                start=self._parser._start):
+                        append((event, start(tag, attrib_in)))
+                    parser.StartElementHandler = handler
+            elif event == "end":
+                def handler(tag, event=event, append=append,
+                            end=self._parser._end):
+                    append((event, end(tag)))
+                parser.EndElementHandler = handler
+            elif event == "start-ns":
+                def handler(prefix, uri, event=event, append=append):
+                    try:
+                        uri = (uri or "").encode("ascii")
+                    except UnicodeError:
+                        pass
+                    append((event, (prefix or "", uri or "")))
+                parser.StartNamespaceDeclHandler = handler
+            elif event == "end-ns":
+                def handler(prefix, event=event, append=append):
+                    append((event, None))
+                parser.EndNamespaceDeclHandler = handler
+            else:
+                raise ValueError("unknown event %r" % event)
+
+    def next(self):
+        while 1:
+            try:
+                item = self._events[self._index]
+                self._index += 1
+                return item
+            except IndexError:
+                pass
+            if self._error:
+                e = self._error
+                self._error = None
+                raise e
+            if self._parser is None:
+                self.root = self._root
+                if self._close_file:
+                    self._file.close()
+                raise StopIteration
+            # load event buffer
+            del self._events[:]
+            self._index = 0
+            data = self._file.read(16384)
+            if data:
+                try:
+                    self._parser.feed(data)
+                except SyntaxError as exc:
+                    self._error = exc
+            else:
+                self._root = self._parser.close()
+                self._parser = None
+
+    def __iter__(self):
+        return self
+
+##
+# Parses an XML document from a string constant.  This function can
+# be used to embed "XML literals" in Python code.
+#
+# @param source A string containing XML data.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return An Element instance.
+# @defreturn Element
+
+def XML(text, parser=None):
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    parser.feed(text)
+    return parser.close()
+
+##
+# Parses an XML document from a string constant, and also returns
+# a dictionary which maps from element id:s to elements.
+#
+# @param source A string containing XML data.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return A tuple containing an Element instance and a dictionary.
+# @defreturn (Element, dictionary)
+
+def XMLID(text, parser=None):
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    parser.feed(text)
+    tree = parser.close()
+    ids = {}
+    for elem in tree.iter():
+        id = elem.get("id")
+        if id:
+            ids[id] = elem
+    return tree, ids
+
+##
+# Parses an XML document from a string constant.  Same as {@link #XML}.
+#
+# @def fromstring(text)
+# @param source A string containing XML data.
+# @return An Element instance.
+# @defreturn Element
+
+fromstring = XML
+
+##
+# Parses an XML document from a sequence of string fragments.
+#
+# @param sequence A list or other sequence containing XML data fragments.
+# @param parser An optional parser instance.  If not given, the
+#     standard {@link XMLParser} parser is used.
+# @return An Element instance.
+# @defreturn Element
+# @since 1.3
+
+def fromstringlist(sequence, parser=None):
+    if not parser:
+        parser = XMLParser(target=TreeBuilder())
+    for text in sequence:
+        parser.feed(text)
+    return parser.close()
+
+# --------------------------------------------------------------------
+
+##
+# Generic element structure builder.  This builder converts a sequence
+# of {@link #TreeBuilder.start}, {@link #TreeBuilder.data}, and {@link
+# #TreeBuilder.end} method calls to a well-formed element structure.
+# <p>
+# You can use this class to build an element structure using a custom XML
+# parser, or a parser for some other XML-like format.
+#
+# @param element_factory Optional element factory.  This factory
+#    is called to create new Element instances, as necessary.
+
+class TreeBuilder(object):
+
+    def __init__(self, element_factory=None):
+        self._data = [] # data collector
+        self._elem = [] # element stack
+        self._last = None # last element
+        self._tail = None # true if we're after an end tag
+        if element_factory is None:
+            element_factory = Element
+        self._factory = element_factory
+
+    ##
+    # Flushes the builder buffers, and returns the toplevel document
+    # element.
+    #
+    # @return An Element instance.
+    # @defreturn Element
+
+    def close(self):
+        assert len(self._elem) == 0, "missing end tags"
+        assert self._last is not None, "missing toplevel element"
+        return self._last
+
+    def _flush(self):
+        if self._data:
+            if self._last is not None:
+                text = "".join(self._data)
+                if self._tail:
+                    assert self._last.tail is None, "internal error (tail)"
+                    self._last.tail = text
+                else:
+                    assert self._last.text is None, "internal error (text)"
+                    self._last.text = text
+            self._data = []
+
+    ##
+    # Adds text to the current element.
+    #
+    # @param data A string.  This should be either an 8-bit string
+    #    containing ASCII text, or a Unicode string.
+
+    def data(self, data):
+        self._data.append(data)
+
+    ##
+    # Opens a new element.
+    #
+    # @param tag The element name.
+    # @param attrib A dictionary containing element attributes.
+    # @return The opened element.
+    # @defreturn Element
+
+    def start(self, tag, attrs):
+        self._flush()
+        self._last = elem = self._factory(tag, attrs)
+        if self._elem:
+            self._elem[-1].append(elem)
+        self._elem.append(elem)
+        self._tail = 0
+        return elem
+
+    ##
+    # Closes the current element.
+    #
+    # @param tag The element name.
+    # @return The closed element.
+    # @defreturn Element
+
+    def end(self, tag):
+        self._flush()
+        self._last = self._elem.pop()
+        assert self._last.tag == tag,\
+               "end tag mismatch (expected %s, got %s)" % (
+                   self._last.tag, tag)
+        self._tail = 1
+        return self._last
+
+##
+# Element structure builder for XML source data, based on the
+# <b>expat</b> parser.
+#
+# @keyparam target Target object.  If omitted, the builder uses an
+#     instance of the standard {@link #TreeBuilder} class.
+# @keyparam html Predefine HTML entities.  This flag is not supported
+#     by the current implementation.
+# @keyparam encoding Optional encoding.  If given, the value overrides
+#     the encoding specified in the XML file.
+# @see #ElementTree
+# @see #TreeBuilder
+
+class XMLParser(object):
+
+    def __init__(self, html=0, target=None, encoding=None):
+        try:
+            from xml.parsers import expat
+        except ImportError:
+            try:
+                import pyexpat as expat
+            except ImportError:
+                raise ImportError(
+                    "No module named expat; use SimpleXMLTreeBuilder instead"
+                    )
+        parser = expat.ParserCreate(encoding, "}")
+        if target is None:
+            target = TreeBuilder()
+        # underscored names are provided for compatibility only
+        self.parser = self._parser = parser
+        self.target = self._target = target
+        self._error = expat.error
+        self._names = {} # name memo cache
+        # callbacks
+        parser.DefaultHandlerExpand = self._default
+        parser.StartElementHandler = self._start
+        parser.EndElementHandler = self._end
+        parser.CharacterDataHandler = self._data
+        # optional callbacks
+        parser.CommentHandler = self._comment
+        parser.ProcessingInstructionHandler = self._pi
+        # let expat do the buffering, if supported
+        try:
+            self._parser.buffer_text = 1
+        except AttributeError:
+            pass
+        # use new-style attribute handling, if supported
+        try:
+            self._parser.ordered_attributes = 1
+            self._parser.specified_attributes = 1
+            parser.StartElementHandler = self._start_list
+        except AttributeError:
+            pass
+        self._doctype = None
+        self.entity = {}
+        try:
+            self.version = "Expat %d.%d.%d" % expat.version_info
+        except AttributeError:
+            pass # unknown
+
+    def _raiseerror(self, value):
+        err = ParseError(value)
+        err.code = value.code
+        err.position = value.lineno, value.offset
+        raise err
+
+    def _fixtext(self, text):
+        # convert text string to ascii, if possible
+        try:
+            return text.encode("ascii")
+        except UnicodeError:
+            return text
+
+    def _fixname(self, key):
+        # expand qname, and convert name string to ascii, if possible
+        try:
+            name = self._names[key]
+        except KeyError:
+            name = key
+            if "}" in name:
+                name = "{" + name
+            self._names[key] = name = self._fixtext(name)
+        return name
+
+    def _start(self, tag, attrib_in):
+        fixname = self._fixname
+        fixtext = self._fixtext
+        tag = fixname(tag)
+        attrib = {}
+        for key, value in attrib_in.items():
+            attrib[fixname(key)] = fixtext(value)
+        return self.target.start(tag, attrib)
+
+    def _start_list(self, tag, attrib_in):
+        fixname = self._fixname
+        fixtext = self._fixtext
+        tag = fixname(tag)
+        attrib = {}
+        if attrib_in:
+            for i in range(0, len(attrib_in), 2):
+                attrib[fixname(attrib_in[i])] = fixtext(attrib_in[i+1])
+        return self.target.start(tag, attrib)
+
+    def _data(self, text):
+        return self.target.data(self._fixtext(text))
+
+    def _end(self, tag):
+        return self.target.end(self._fixname(tag))
+
+    def _comment(self, data):
+        try:
+            comment = self.target.comment
+        except AttributeError:
+            pass
+        else:
+            return comment(self._fixtext(data))
+
+    def _pi(self, target, data):
+        try:
+            pi = self.target.pi
+        except AttributeError:
+            pass
+        else:
+            return pi(self._fixtext(target), self._fixtext(data))
+
+    def _default(self, text):
+        prefix = text[:1]
+        if prefix == "&":
+            # deal with undefined entities
+            try:
+                self.target.data(self.entity[text[1:-1]])
+            except KeyError:
+                from xml.parsers import expat
+                err = expat.error(
+                    "undefined entity %s: line %d, column %d" %
+                    (text, self._parser.ErrorLineNumber,
+                    self._parser.ErrorColumnNumber)
+                    )
+                err.code = 11 # XML_ERROR_UNDEFINED_ENTITY
+                err.lineno = self._parser.ErrorLineNumber
+                err.offset = self._parser.ErrorColumnNumber
+                raise err
+        elif prefix == "<" and text[:9] == "<!DOCTYPE":
+            self._doctype = [] # inside a doctype declaration
+        elif self._doctype is not None:
+            # parse doctype contents
+            if prefix == ">":
+                self._doctype = None
+                return
+            text = text.strip()
+            if not text:
+                return
+            self._doctype.append(text)
+            n = len(self._doctype)
+            if n > 2:
+                type = self._doctype[1]
+                if type == "PUBLIC" and n == 4:
+                    name, type, pubid, system = self._doctype
+                elif type == "SYSTEM" and n == 3:
+                    name, type, system = self._doctype
+                    pubid = None
+                else:
+                    return
+                if pubid:
+                    pubid = pubid[1:-1]
+                if hasattr(self.target, "doctype"):
+                    self.target.doctype(name, pubid, system[1:-1])
+                elif self.doctype is not self._XMLParser__doctype:
+                    # warn about deprecated call
+                    self._XMLParser__doctype(name, pubid, system[1:-1])
+                    self.doctype(name, pubid, system[1:-1])
+                self._doctype = None
+
+    ##
+    # (Deprecated) Handles a doctype declaration.
+    #
+    # @param name Doctype name.
+    # @param pubid Public identifier.
+    # @param system System identifier.
+
+    def doctype(self, name, pubid, system):
+        """This method of XMLParser is deprecated."""
+        warnings.warn(
+            "This method of XMLParser is deprecated.  Define doctype() "
+            "method on the TreeBuilder target.",
+            DeprecationWarning,
+            )
+
+    # sentinel, if doctype is redefined in a subclass
+    __doctype = doctype
+
+    ##
+    # Feeds data to the parser.
+    #
+    # @param data Encoded data.
+
+    def feed(self, data):
+        try:
+            self._parser.Parse(data, 0)
+        except self._error, v:
+            self._raiseerror(v)
+
+    ##
+    # Finishes feeding data to the parser.
+    #
+    # @return An element structure.
+    # @defreturn Element
+
+    def close(self):
+        try:
+            self._parser.Parse("", 1) # end of data
+        except self._error, v:
+            self._raiseerror(v)
+        tree = self.target.close()
+        del self.target, self._parser # get rid of circular references
+        return tree
+
+# compatibility
+XMLTreeBuilder = XMLParser
+
+# workaround circular import.
+try:
+    from ElementC14N import _serialize_c14n
+    _serialize["c14n"] = _serialize_c14n
+except ImportError:
+    pass
diff --git a/InstallerResources/third_party/etree/__init__.py b/InstallerResources/third_party/etree/__init__.py
index 1fd62da..27fd8f6 100644
--- a/InstallerResources/third_party/etree/__init__.py
+++ b/InstallerResources/third_party/etree/__init__.py
@@ -1,33 +1,33 @@
-# $Id: __init__.py 3375 2008-02-13 08:05:08Z fredrik $

-# elementtree package

-

-# --------------------------------------------------------------------

-# The ElementTree toolkit is

-#

-# Copyright (c) 1999-2008 by Fredrik Lundh

-#

-# By obtaining, using, and/or copying this software and/or its

-# associated documentation, you agree that you have read, understood,

-# and will comply with the following terms and conditions:

-#

-# Permission to use, copy, modify, and distribute this software and

-# its associated documentation for any purpose and without fee is

-# hereby granted, provided that the above copyright notice appears in

-# all copies, and that both that copyright notice and this permission

-# notice appear in supporting documentation, and that the name of

-# Secret Labs AB or the author not be used in advertising or publicity

-# pertaining to distribution of the software without specific, written

-# prior permission.

-#

-# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD

-# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-

-# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR

-# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY

-# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

-# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS

-# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE

-# OF THIS SOFTWARE.

-# --------------------------------------------------------------------

-

-# Licensed to PSF under a Contributor Agreement.

-# See http://www.python.org/psf/license for licensing details.

+# $Id: __init__.py 3375 2008-02-13 08:05:08Z fredrik $
+# elementtree package
+
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2008 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/psf/license for licensing details.
diff --git a/InstallerResources/third_party/etree/cElementTree.py b/InstallerResources/third_party/etree/cElementTree.py
index db12fde..a6f127a 100644
--- a/InstallerResources/third_party/etree/cElementTree.py
+++ b/InstallerResources/third_party/etree/cElementTree.py
@@ -1,3 +1,3 @@
-# Wrapper module for _elementtree

-

-from _elementtree import *

+# Wrapper module for _elementtree
+
+from _elementtree import *
diff --git a/InstallerResources/xml_patch.py b/InstallerResources/xml_patch.py
index 256e838..5665500 100644
--- a/InstallerResources/xml_patch.py
+++ b/InstallerResources/xml_patch.py
@@ -1,174 +1,174 @@
-#!/usr/bin/env python

-# Copyright (c) 2012 The Chromium Authors. All rights reserved.

-# Use of this source code is governed by a BSD-style license that can be

-# found in the LICENSE file.

-

-""" This module is a utility for applying an xml patch to an xml file.

-

-The format of the patch is described in the documentation for

-the patch_xml() function.

-"""

-

-import collections

-import copy

-import third_party.etree.ElementTree as ElementTree

-

-

-def PatchXML(source_xml_tree, patch_xml_tree):

-  """Applies a patch to the source xml and returns a new merged xml tree.

-

-  Given a patch xml tree, it applies the patch to the source xml tree

-  and returns the resulting modified xml tree.

-

-  Patching is done by reading the patch_xml_tree for an element and then

-  finding the in-order matching element in the source_xml_tree. Both elements

-  are entered to look for matching sub-elements recursively.

-

-  Patching occurs when a <PatchRemove> or <PatchAdd> element is encountered

-  in the patch xml tree. For a remove operation, the first element in the

-  source_xml_tree from the current read position that matches the contents of

-  the <PatchRemove> element is removed. The read pointer is updated accordingly.

-  For an add operation, the contents of the <PatchAdd> element is added at the

-  current reading location.

-

-  If for example, an add operation needs to be done after certain elements,

-  the elements can be listed before the <PatchAdd> operation so that they are

-  matched first before the add operation.

-

-  Example:

-  Source file:

-  <a>

-    <b></b>

-    <c></c>

-  </a>

-

-  Patch file:

-  <a>

-    <b></b>

-    <PatchAdd><zzz></zzz></PatchAdd>

-  </a>

-

-  Result:

-  <a>

-    <b></b>

-    <zzz></zzz>

-    <c></c>

-  </a>

-

-

-  Args:

-    source_xml_tree: An ElementTree object with base xml to change.

-    patch_xml_tree: An ElementTree object with xml to apply. See above notes

-      for the xml structure of a patch.

-

-  Returns:

-    A new xml tree based on source with the patch applied.

-

-  Raises:

-    General Exception indicating a merge error has occured.

-  """

-  source = source_xml_tree.getroot()

-  patch = patch_xml_tree.getroot()

-  if not ElementMatch(source, patch):

-    raise Exception('Root nodes do not match, cannot merge')

-  return ElementTree.ElementTree(MergeElement(source, patch))

-

-

-def MergeElement(source_elem, patch_elem):

-  """Applies a single patch element to a single source element.

-

-  The merge is applied recursively for sub-elements. See the documentation

-  for patch_xml() for a description of how patching is done.

-

-  Args:

-    source_elem: An Element object with xml to change.

-    patch_elem: An Element object with xml to apply.

-

-  Returns:

-    A new xml Element with the patch_elem applied to source_elem.

-

-  Raises:

-    General Exception indicating a merge error has occured.

-  """

-  assert ElementMatch(source_elem, patch_elem), 'Mismatched merge'

-

-  # Create a new element by copying tags from source. Below we will merge

-  # the subelements of source with the patch and put them in new_element.

-  new_element = ElementTree.Element(source_elem.tag, source_elem.attrib)

-

-  patch_children = list(patch_elem)

-  patch_index = 0

-  remove_targets = collections.deque()

-  find_target = None

-  for source_child in source_elem:

-    # If we have no current patch operation then read the next patch element.

-    while (len(remove_targets) == 0 and find_target is None and

-        patch_index < len(patch_children)):

-

-      # PatchAdd operation.

-      if IsPatchAddTag(patch_children[patch_index].tag):

-        for addition in patch_children[patch_index]:

-          new_element.append(copy.deepcopy(addition))

-

-      # Start a remove operation by creating a list of elements to skip adding.

-      elif IsPatchRemoveTag(patch_children[patch_index].tag):

-        remove_targets = collections.deque(

-            patch_children[patch_index])

-

-      # Not an Add or Remove, must be a find target (find operation).

-      else:

-        find_target = patch_children[patch_index]

-      patch_index += 1

-

-    # A remove operation means skipping adding the element to new_element.

-    if (len(remove_targets) > 0 and

-        ElementMatch(source_child, remove_targets[0])):

-      remove_targets.popleft()

-

-    # A matching find target means we must merge the sub-elements.

-    elif find_target is not None and ElementMatch(source_child, find_target):

-      merge = MergeElement(source_child, find_target)

-      new_element.append(copy.deepcopy(merge))

-      find_target = None

-

-    # Otherwise this source element doesn't match any patch operations, add it.

-    else:

-      new_element.append(copy.deepcopy(source_child))

-

-  # Raise exceptions if find/remove didn't finish before the end of the source.

-  if find_target is not None:

-    raise Exception('Find operation never matched:' + find_target.tag)

-  elif len(remove_targets) != 0:

-    raise Exception('Remove operation never matched: ' + remove_targets)

-

-  # We may have more add operations after source has run empty:

-  while patch_index < len(patch_children):

-    if IsPatchAddTag(patch_children[patch_index].tag):

-      for addition in patch_children[patch_index]:

-        new_element.append(copy.deepcopy(addition))

-      patch_index += 1

-    else:

-      raise Exception('Non-add operation attempted after source end. ' +

-                      'Tag: %s, Children %s' %

-                      (patch_children[patch_index].tag,

-                       list(patch_children[patch_index])))

-

-  return new_element

-

-

-def ElementMatch(elem1, elem2):

-  return elem1.tag == elem2.tag and elem1.attrib == elem2.attrib

-

-

-def IsPatchAddTag(tag):

-  # We look at the end of the tag because we need to ignore the namespace.

-  # Because the tag can be a sub-element of arbitrary elements it could inherit

-  # any default namespace.

-  return tag.endswith('PatchAdd')

-

-

-def IsPatchRemoveTag(tag):

-  # We look at the end of the tag because we need to ignore the namespace.

-  # Because the tag can be a sub-element of arbitrary elements it could inherit

-  # any default namespace.

-  return tag.endswith('PatchRemove')

+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" This module is a utility for applying an xml patch to an xml file.
+
+The format of the patch is described in the documentation for
+the patch_xml() function.
+"""
+
+import collections
+import copy
+import third_party.etree.ElementTree as ElementTree
+
+
+def PatchXML(source_xml_tree, patch_xml_tree):
+  """Applies a patch to the source xml and returns a new merged xml tree.
+
+  Given a patch xml tree, it applies the patch to the source xml tree
+  and returns the resulting modified xml tree.
+
+  Patching is done by reading the patch_xml_tree for an element and then
+  finding the in-order matching element in the source_xml_tree. Both elements
+  are entered to look for matching sub-elements recursively.
+
+  Patching occurs when a <PatchRemove> or <PatchAdd> element is encountered
+  in the patch xml tree. For a remove operation, the first element in the
+  source_xml_tree from the current read position that matches the contents of
+  the <PatchRemove> element is removed. The read pointer is updated accordingly.
+  For an add operation, the contents of the <PatchAdd> element is added at the
+  current reading location.
+
+  If for example, an add operation needs to be done after certain elements,
+  the elements can be listed before the <PatchAdd> operation so that they are
+  matched first before the add operation.
+
+  Example:
+  Source file:
+  <a>
+    <b></b>
+    <c></c>
+  </a>
+
+  Patch file:
+  <a>
+    <b></b>
+    <PatchAdd><zzz></zzz></PatchAdd>
+  </a>
+
+  Result:
+  <a>
+    <b></b>
+    <zzz></zzz>
+    <c></c>
+  </a>
+
+
+  Args:
+    source_xml_tree: An ElementTree object with base xml to change.
+    patch_xml_tree: An ElementTree object with xml to apply. See above notes
+      for the xml structure of a patch.
+
+  Returns:
+    A new xml tree based on source with the patch applied.
+
+  Raises:
+    General Exception indicating a merge error has occured.
+  """
+  source = source_xml_tree.getroot()
+  patch = patch_xml_tree.getroot()
+  if not ElementMatch(source, patch):
+    raise Exception('Root nodes do not match, cannot merge')
+  return ElementTree.ElementTree(MergeElement(source, patch))
+
+
+def MergeElement(source_elem, patch_elem):
+  """Applies a single patch element to a single source element.
+
+  The merge is applied recursively for sub-elements. See the documentation
+  for patch_xml() for a description of how patching is done.
+
+  Args:
+    source_elem: An Element object with xml to change.
+    patch_elem: An Element object with xml to apply.
+
+  Returns:
+    A new xml Element with the patch_elem applied to source_elem.
+
+  Raises:
+    General Exception indicating a merge error has occured.
+  """
+  assert ElementMatch(source_elem, patch_elem), 'Mismatched merge'
+
+  # Create a new element by copying tags from source. Below we will merge
+  # the subelements of source with the patch and put them in new_element.
+  new_element = ElementTree.Element(source_elem.tag, source_elem.attrib)
+
+  patch_children = list(patch_elem)
+  patch_index = 0
+  remove_targets = collections.deque()
+  find_target = None
+  for source_child in source_elem:
+    # If we have no current patch operation then read the next patch element.
+    while (len(remove_targets) == 0 and find_target is None and
+        patch_index < len(patch_children)):
+
+      # PatchAdd operation.
+      if IsPatchAddTag(patch_children[patch_index].tag):
+        for addition in patch_children[patch_index]:
+          new_element.append(copy.deepcopy(addition))
+
+      # Start a remove operation by creating a list of elements to skip adding.
+      elif IsPatchRemoveTag(patch_children[patch_index].tag):
+        remove_targets = collections.deque(
+            patch_children[patch_index])
+
+      # Not an Add or Remove, must be a find target (find operation).
+      else:
+        find_target = patch_children[patch_index]
+      patch_index += 1
+
+    # A remove operation means skipping adding the element to new_element.
+    if (len(remove_targets) > 0 and
+        ElementMatch(source_child, remove_targets[0])):
+      remove_targets.popleft()
+
+    # A matching find target means we must merge the sub-elements.
+    elif find_target is not None and ElementMatch(source_child, find_target):
+      merge = MergeElement(source_child, find_target)
+      new_element.append(copy.deepcopy(merge))
+      find_target = None
+
+    # Otherwise this source element doesn't match any patch operations, add it.
+    else:
+      new_element.append(copy.deepcopy(source_child))
+
+  # Raise exceptions if find/remove didn't finish before the end of the source.
+  if find_target is not None:
+    raise Exception('Find operation never matched:' + find_target.tag)
+  elif len(remove_targets) != 0:
+    raise Exception('Remove operation never matched: ' + remove_targets)
+
+  # We may have more add operations after source has run empty:
+  while patch_index < len(patch_children):
+    if IsPatchAddTag(patch_children[patch_index].tag):
+      for addition in patch_children[patch_index]:
+        new_element.append(copy.deepcopy(addition))
+      patch_index += 1
+    else:
+      raise Exception('Non-add operation attempted after source end. ' +
+                      'Tag: %s, Children %s' %
+                      (patch_children[patch_index].tag,
+                       list(patch_children[patch_index])))
+
+  return new_element
+
+
+def ElementMatch(elem1, elem2):
+  return elem1.tag == elem2.tag and elem1.attrib == elem2.attrib
+
+
+def IsPatchAddTag(tag):
+  # We look at the end of the tag because we need to ignore the namespace.
+  # Because the tag can be a sub-element of arbitrary elements it could inherit
+  # any default namespace.
+  return tag.endswith('PatchAdd')
+
+
+def IsPatchRemoveTag(tag):
+  # We look at the end of the tag because we need to ignore the namespace.
+  # Because the tag can be a sub-element of arbitrary elements it could inherit
+  # any default namespace.
+  return tag.endswith('PatchRemove')
diff --git a/NaCl.Build.CPPTasks/DependencyParser.cs b/NaCl.Build.CPPTasks/DependencyParser.cs
index 9a51660..ab39f6e 100644
--- a/NaCl.Build.CPPTasks/DependencyParser.cs
+++ b/NaCl.Build.CPPTasks/DependencyParser.cs
@@ -1,53 +1,53 @@
-using System;

-using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-

-using System.IO;

-

-namespace NaCl.Build.CPPTasks

-{

-    class DependencyParser

-    {

-        private static char[]   elementEndings = new char[] { ' ', '\n', '\\' };

-        private List<string>    m_dependencies;

-        public List<String> Dependencies

-        {

-            get

-            {

-                return m_dependencies;

-            }

-        }

-

-        public DependencyParser(string filename)

-        {

-            m_dependencies = new List<string>();

-

-            using (StreamReader reader = new StreamReader(filename, Encoding.ASCII))

-            {

-                while (!reader.EndOfStream)

-                {

-                    string str = reader.ReadLine();

-                    ParseLine(str);

-                }

-                reader.Close();

-            }

-        }

-

-        private void ParseLine(string line)

-        {

-            string[] paths = line.Split(elementEndings, StringSplitOptions.RemoveEmptyEntries);

-

-            foreach (string path in paths)

-            {

-                // ignore the source object file

-                // assumes .o file is only possible file ending with 'o'

-                if (path.ElementAt(path.Length - 1) != 'o' && path.ElementAt(path.Length - 1) != ':')

-                {

-                    string newDependency = GCCUtilities.Convert_Path_Posix_To_Windows(path);

-                    m_dependencies.Add(newDependency);

-                }

-            }

-        }

-    }

-}

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using System.IO;
+
+namespace NaCl.Build.CPPTasks
+{
+    class DependencyParser
+    {
+        private static char[]   elementEndings = new char[] { ' ', '\n', '\\' };
+        private List<string>    m_dependencies;
+        public List<String> Dependencies
+        {
+            get
+            {
+                return m_dependencies;
+            }
+        }
+
+        public DependencyParser(string filename)
+        {
+            m_dependencies = new List<string>();
+
+            using (StreamReader reader = new StreamReader(filename, Encoding.ASCII))
+            {
+                while (!reader.EndOfStream)
+                {
+                    string str = reader.ReadLine();
+                    ParseLine(str);
+                }
+                reader.Close();
+            }
+        }
+
+        private void ParseLine(string line)
+        {
+            string[] paths = line.Split(elementEndings, StringSplitOptions.RemoveEmptyEntries);
+
+            foreach (string path in paths)
+            {
+                // ignore the source object file
+                // assumes .o file is only possible file ending with 'o'
+                if (path.ElementAt(path.Length - 1) != 'o' && path.ElementAt(path.Length - 1) != ':')
+                {
+                    string newDependency = GCCUtilities.Convert_Path_Posix_To_Windows(path);
+                    m_dependencies.Add(newDependency);
+                }
+            }
+        }
+    }
+}
diff --git a/NaCl.Build.CPPTasks/GCCUtilities.cs b/NaCl.Build.CPPTasks/GCCUtilities.cs
index 2db604a..57ea253 100644
--- a/NaCl.Build.CPPTasks/GCCUtilities.cs
+++ b/NaCl.Build.CPPTasks/GCCUtilities.cs
@@ -1,101 +1,101 @@
-using System;

-using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-

-using System.IO;

-using System.Text.RegularExpressions;

-

-namespace NaCl.Build.CPPTasks

-{

-    class GCCUtilities

-    {

-        public const int s_CommandLineLength = 256;

-

-        public static string Convert_Path_Windows_To_Posix(string path)

-        {

-            return path.Replace('\\', '/');

-        }

-

-        public static string Convert_Path_Posix_To_Windows(string path)

-        {

-            path = path.Replace('/', '\\');

-            // also make double backslashes a single slash

-            // TODO: speed this up by iterating instead of two replaces

-            return path.Replace("\\\\", "\\");

-        }

-

-        // replace GCC error are warning output to Visual Studio format to support going to source code from error output.

-        public static string Convert_Output_GCC_to_VS(string line)

-        {

-            string result;

-            foreach (GCCRegexLineConverter converter in s_RegexConverters)

-            {

-                result = converter.Convert(line);

-                if (result.Length > 0)

-                {

-                    return result;

-                }

-            }

-

-            return line;

-        }

-

-        private class GCCRegexLineConverter

-        {

-            public Regex OutputExpression { get; set; }

-

-            //public string OutputIdentifier { get; set; }

-            public string FilenameIdentifier { get; set; }

-            public string RemainderIdentifier { get; set; }

-

-            // returns empty string if cannot convert.

-            public string Convert(string line)

-            {

-                //Regex expression = new Regex(OutputIdentifier);

-                if (OutputExpression.IsMatch(line))

-                {

-                    string filename = OutputExpression.Replace(line, FilenameIdentifier);

-

-                    // GetFullPath may throw an exception.

-                    try

-                    {

-                        string fullPath = Path.GetFullPath(filename);

-                        string remainder = OutputExpression.Replace(line, RemainderIdentifier);

-

-                        string newLine = fullPath + remainder;

-

-                        return newLine;

-                    }

-                    catch

-                    {

-                    }

-                }

-

-                return string.Empty;

-            }

-        } // GCCRegexLineConverter

-

-        private static readonly List<GCCRegexLineConverter> s_RegexConverters = new List<GCCRegexLineConverter> 

-        {

-            new GCCRegexLineConverter 

-            {

-                OutputExpression =      new Regex(@"^\s*(.?.?[^:]*.*?):([1-9]\d*):([1-9]\d*):(.*$)"),

-                FilenameIdentifier =    @"$1",

-                RemainderIdentifier =   @"($2,$3):$4"

-            },

-            new GCCRegexLineConverter 

-            {

-                OutputExpression =      new Regex(@"^\s*(.?.?[^:]*.*?):([1-9]\d*):(.*$)"),

-                FilenameIdentifier =    @"$1",

-                RemainderIdentifier =   @"($2):$3"

-            },

-            new GCCRegexLineConverter 

-            {

-                OutputExpression =      new Regex(@"^\s*(.?.?[^:]*.*?):(.?.?[^:]*.*?):([1-9]\d*):(.*$)"),

-                FilenameIdentifier =    @"$2",

-                RemainderIdentifier =   @"($3):'$1' $4"

-            }

-        };

-    } // GCCUtilities

-} // namespace

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace NaCl.Build.CPPTasks
+{
+    class GCCUtilities
+    {
+        public const int s_CommandLineLength = 256;
+
+        public static string Convert_Path_Windows_To_Posix(string path)
+        {
+            return path.Replace('\\', '/');
+        }
+
+        public static string Convert_Path_Posix_To_Windows(string path)
+        {
+            path = path.Replace('/', '\\');
+            // also make double backslashes a single slash
+            // TODO: speed this up by iterating instead of two replaces
+            return path.Replace("\\\\", "\\");
+        }
+
+        // replace GCC error are warning output to Visual Studio format to support going to source code from error output.
+        public static string Convert_Output_GCC_to_VS(string line)
+        {
+            string result;
+            foreach (GCCRegexLineConverter converter in s_RegexConverters)
+            {
+                result = converter.Convert(line);
+                if (result.Length > 0)
+                {
+                    return result;
+                }
+            }
+
+            return line;
+        }
+
+        private class GCCRegexLineConverter
+        {
+            public Regex OutputExpression { get; set; }
+
+            //public string OutputIdentifier { get; set; }
+            public string FilenameIdentifier { get; set; }
+            public string RemainderIdentifier { get; set; }
+
+            // returns empty string if cannot convert.
+            public string Convert(string line)
+            {
+                //Regex expression = new Regex(OutputIdentifier);
+                if (OutputExpression.IsMatch(line))
+                {
+                    string filename = OutputExpression.Replace(line, FilenameIdentifier);
+
+                    // GetFullPath may throw an exception.
+                    try
+                    {
+                        string fullPath = Path.GetFullPath(filename);
+                        string remainder = OutputExpression.Replace(line, RemainderIdentifier);
+
+                        string newLine = fullPath + remainder;
+
+                        return newLine;
+                    }
+                    catch
+                    {
+                    }
+                }
+
+                return string.Empty;
+            }
+        } // GCCRegexLineConverter
+
+        private static readonly List<GCCRegexLineConverter> s_RegexConverters = new List<GCCRegexLineConverter> 
+        {
+            new GCCRegexLineConverter 
+            {
+                OutputExpression =      new Regex(@"^\s*(.?.?[^:]*.*?):([1-9]\d*):([1-9]\d*):(.*$)"),
+                FilenameIdentifier =    @"$1",
+                RemainderIdentifier =   @"($2,$3):$4"
+            },
+            new GCCRegexLineConverter 
+            {
+                OutputExpression =      new Regex(@"^\s*(.?.?[^:]*.*?):([1-9]\d*):(.*$)"),
+                FilenameIdentifier =    @"$1",
+                RemainderIdentifier =   @"($2):$3"
+            },
+            new GCCRegexLineConverter 
+            {
+                OutputExpression =      new Regex(@"^\s*(.?.?[^:]*.*?):(.?.?[^:]*.*?):([1-9]\d*):(.*$)"),
+                FilenameIdentifier =    @"$2",
+                RemainderIdentifier =   @"($3):'$1' $4"
+            }
+        };
+    } // GCCUtilities
+} // namespace
diff --git a/NaCl.Build.CPPTasks/NaClCompile.cs b/NaCl.Build.CPPTasks/NaClCompile.cs
index 7c91a26..5682575 100644
--- a/NaCl.Build.CPPTasks/NaClCompile.cs
+++ b/NaCl.Build.CPPTasks/NaClCompile.cs
@@ -1,645 +1,645 @@
-

-using System;

-using System.Collections.Generic;

-using System.Text;

-using System.Collections;

-using System.IO;

-using System.Reflection;

-using System.Resources;

-using Microsoft.Build.Framework;

-using Microsoft.Build.Utilities;

-

-using System.Diagnostics;

-

-namespace NaCl.Build.CPPTasks

-{

-    public class NaClCompile : ToolTask

-    {

-        private XamlParser m_XamlParser;

-        private ITaskItem[] excludedInputPaths;

-        private ITaskItem[] tlogReadFiles;

-        private ITaskItem tlogCommandFile;

-        private ITaskItem[] tlogWriteFiles;

-        private CanonicalTrackedInputFiles trackedInputFiles;

-        private bool skippedExecution;

-        private ITaskItem[] compileSourceList;

-        public bool BuildingInIDE { get; set; }

-        private string m_toolname;

-        private bool trackFileAccess;

-        private bool minimalRebuildFromTracking;

-        private string pathToLog;

-

-        [Required]

-        public string PropertiesFile { get; set; }

-

-        [Required]

-        public ITaskItem[] Sources { get; set; }

-

-        [Required]

-        public string NaCLCompilerPath { get; set; }

-

-        [Required]

-        public string OutputCommandLine { get; set; }

-

-        [Required]

-        public string TrackerLogDirectory { get; set; }

-

-

-        protected override string GenerateFullPathToTool() { return ToolName; }

-

-        public NaClCompile()

-            : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", Assembly.GetExecutingAssembly()))

-        {

-            this.pathToLog = string.Empty;

-            this.EnvironmentVariables = new string []{"CYGWIN=nodosfilewarning", "LC_CTYPE=C"};

-        }

-

-        protected IDictionary<string, string> GenerateCommandLinesFromTlog()

-        {

-            IDictionary<string, string> cmdLineDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

-            string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath");

-            if (File.Exists(tlogFilename))

-            {

-                using (StreamReader reader = File.OpenText(tlogFilename))

-                {

-                    string filename = string.Empty;

-                    for (string lineStr = reader.ReadLine(); lineStr != null; lineStr = reader.ReadLine())

-                    {

-                        if (lineStr.Length == 0 ||

-                            (lineStr[0] == '^' && lineStr.Length == 1))

-                        {

-                            Log.LogMessage(MessageImportance.High, "Invalid line in command tlog");

-                            break;

-                        }

-                        else if (lineStr[0] == '^')

-                        {

-                            filename = lineStr.Substring(1);

-                        }

-                        else

-                        {

-                            cmdLineDictionary[filename] = lineStr;

-                        }

-                    }

-                }

-            }

-            return cmdLineDictionary;

-        }

-

-        protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)

-        {

-            base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(singleLine), messageImportance);

-        }

-

-        private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTrackedOutputFiles outputs)

-        {

-            string trackerPath = Path.GetFullPath(TlogDirectory + ReadTLogFilenames[0]);

-

-            //save tlog for sources not compiled during this execution

-            TaskItem readTrackerItem = new TaskItem(trackerPath);

-            CanonicalTrackedInputFiles files = new CanonicalTrackedInputFiles(new TaskItem[] { readTrackerItem }, Sources, outputs, false, false);

-            files.RemoveEntriesForSource(compiledSources);

-            files.SaveTlog();

-

-            //add tlog information for compiled sources

-            using (StreamWriter writer = new StreamWriter(trackerPath, true, Encoding.Unicode))

-            {

-                foreach (ITaskItem source in compiledSources)

-                {

-                    string sourcePath = Path.GetFullPath(source.ItemSpec).ToUpperInvariant();

-

-                    string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectFileName"));

-                    string depFilePath = Path.ChangeExtension(objectFilePath, ".d");

-

-                    try

-                    {

-                        if (File.Exists(depFilePath) == false)

-                        {

-                            Log.LogMessage(MessageImportance.High, depFilePath + " not found");

-                        }

-                        else

-                        {

-                            writer.WriteLine("^" + sourcePath);

-                            DependencyParser parser = new DependencyParser(depFilePath);

-                            

-                            foreach (string filename in parser.Dependencies)

-                            {

-                                //source itself not required

-                                if (filename == sourcePath)

-                                    continue;

-

-                                if (File.Exists(filename) == false)

-                                {

-                                    Log.LogMessage(MessageImportance.High, "File " + sourcePath + " is missing dependency " + filename);

-                                }

-

-                                writer.WriteLine(filename);

-                            }

-

-                            //remove d file

-                            try

-                            {

-                                File.Delete(depFilePath);

-                            }

-                            finally

-                            {

-

-                            }

-                        }

-

-                    }

-                    catch (Exception)

-                    {

-                        Log.LogError("Failed to update " + readTrackerItem + " for " + sourcePath);

-                    }

-                }

-            }

-        }

-

-        private CanonicalTrackedOutputFiles OutputWriteTrackerLog(ITaskItem[] compiledSources)

-        {

-            string path = Path.Combine(TlogDirectory, WriteTLogFilename);

-            TaskItem item = new TaskItem(path);

-            CanonicalTrackedOutputFiles trackedFiles = new CanonicalTrackedOutputFiles(new TaskItem[] { item });

-

-            foreach (ITaskItem sourceItem in compiledSources)

-            {

-                //remove this entry associated with compiled source which is about to be recomputed

-                trackedFiles.RemoveEntriesForSource(sourceItem);

-

-                //add entry with updated information

-                trackedFiles.AddComputedOutputForSourceRoot( Path.GetFullPath(sourceItem.ItemSpec).ToUpperInvariant(), 

-                                                             Path.GetFullPath(sourceItem.GetMetadata("ObjectFileName")).ToUpperInvariant());

-            }

-

-            //output tlog

-            trackedFiles.SaveTlog();

-

-            return trackedFiles;

-        }

-

-        private void OutputCommandTrackerLog(ITaskItem[] compiledSources)

-        {

-            IDictionary<string, string> commandLines = GenerateCommandLinesFromTlog();

-

-            //

-            if (compiledSources != null)

-            {

-                foreach (ITaskItem source in compiledSources)

-                {

-                    string rmSource = FileTracker.FormatRootingMarker(source);

-                    commandLines[rmSource] = GenerateCommandLineFromProps(source) + " " + source.GetMetadata("FullPath").ToUpperInvariant();

-                }

-            }

-

-            //write tlog

-            using (StreamWriter writer = new StreamWriter(this.TLogCommandFile.GetMetadata("FullPath"), false, Encoding.Unicode))

-            {

-                foreach (KeyValuePair<string, string> p in commandLines)

-                {

-                    string keyLine = "^" + p.Key;

-                    writer.WriteLine(keyLine);

-                    writer.WriteLine(p.Value);

-                }

-            }

-        }

-

-        protected string GenerateCommandLineFromProps(ITaskItem sourceFile)

-        {

-            StringBuilder commandLine = new StringBuilder(GCCUtilities.s_CommandLineLength);

-

-            if (sourceFile != null)

-            {

-                string sourcePath = GCCUtilities.Convert_Path_Windows_To_Posix(sourceFile.ToString());

-

-                // Remove rtti items as they are not relevant in C compilation and will produce warnings

-                if (SourceIsC(sourceFile.ToString()))

-                {

-                    commandLine.Replace("-fno-rtti", "");

-                    commandLine.Replace("-frtti", "");

-                }

-

-                //build command line from components and add required switches

-                string props = m_XamlParser.Parse(sourceFile);

-                commandLine.Append(props);

-                commandLine.Append(" -MD -c ");

-                commandLine.Append(sourcePath);

-

-            }

-

-            return commandLine.ToString();

-        }

-

-        protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSourcesFromTracking, List<ITaskItem> outOfDateSourcesFromCommandLineChanges)

-        {

-            List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSourcesFromTracking);

-

-            foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges)

-            {

-                if (!mergedSources.Contains(item))

-                {

-                    mergedSources.Add(item);

-                }

-            }

-

-            return mergedSources.ToArray();

-        }

-

-        protected bool ForcedRebuildRequired()

-        {

-            string tlogCommandPath = null;

-

-            try

-            {

-                tlogCommandPath = this.TLogCommandFile.GetMetadata("FullPath");

-            }

-            catch (Exception exception)

-            {

-                if (exception is InvalidOperationException || exception is NullReferenceException)

-                    return true;

-                else

-                    throw;

-            }

-

-            //if command tlog file does not exist then force rebuild is required

-            if (File.Exists(tlogCommandPath) == false)

-            {

-                return true;

-            }

-            else

-            {

-                return false;

-            }

-        }

-

-        private int Compile(string pathToTool)

-        {

-            int returnCode = 0;

-

-            foreach (ITaskItem sourceFileItem in CompileSourceList)

-            {

-                try

-                {

-                    string commandLine = GenerateCommandLineFromProps(sourceFileItem);

-

-                    base.Log.LogMessageFromText(Path.GetFileName(sourceFileItem.ToString()), MessageImportance.High);

-

-                    if (OutputCommandLine == "true")

-                    {

-                        string logMessage = pathToTool + " " + commandLine;

-                        Log.LogMessageFromText(logMessage, MessageImportance.High);

-                    }

-                    

-

-                    // compile

-                    returnCode = base.ExecuteTool(pathToTool, commandLine, string.Empty);

-                }

-                catch (Exception)

-                {

-                    returnCode = base.ExitCode;

-                }

-

-                //abort if an error was encountered

-                if (returnCode != 0)

-                {

-                    return returnCode;

-                }

-            }

-            return returnCode;

-        }

-

-        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)

-        {

-            if (File.Exists(pathToTool) == false)

-            {

-                base.Log.LogMessageFromText("Unable to find NaCL compiler: " + pathToTool, MessageImportance.High);

-                return -1;

-            }

-

-            int returnCode = -1;

-

-            try

-            {

-                returnCode = Compile(pathToTool);

-            }

-            finally

-            {

-

-            }

-            return returnCode;

-        }

-

-        protected override bool SkipTaskExecution()

-        {

-            return this.skippedExecution;

-        }

-

-        protected void CalcSourcesToCompile()

-        {

-            if (this.TrackFileAccess || this.MinimalRebuildFromTracking)

-            {

-                this.SetTrackerLogPaths();

-            }

-

-            //check if full recompile is required otherwise perform incremental

-            if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking == false)

-            {

-                this.CompileSourceList = this.Sources;

-                if ((this.CompileSourceList == null) || (this.CompileSourceList.Length == 0))

-                {

-                    this.SkippedExecution = true;

-                }

-            }

-            else

-            {

-                //retrieve list of sources out of date due to command line changes

-                List<ITaskItem> outOfDateSourcesFromCommandLineChanges = this.GetOutOfDateSourcesFromCommandLineChanges();

-

-                //retrieve sources out of date due to tracking

-                CanonicalTrackedOutputFiles trackedOutputFiles = new CanonicalTrackedOutputFiles(this, this.TLogWriteFiles);

-                this.TrackedInputFiles = new CanonicalTrackedInputFiles(this, this.TLogReadFiles, this.Sources, this.ExcludedInputPaths, trackedOutputFiles, true, false);

-                ITaskItem[] outOfDateSourcesFromTracking = this.TrackedInputFiles.ComputeSourcesNeedingCompilation();

-

-                //merge out of date lists

-                this.CompileSourceList = this.MergeOutOfDateSources(outOfDateSourcesFromTracking, outOfDateSourcesFromCommandLineChanges);

-

-                if (this.CompileSourceList.Length == 0)

-                {

-                    this.SkippedExecution = true;

-                }

-                else

-                {

-                    //remove sources to compile from tracked file list

-                    this.TrackedInputFiles.RemoveEntriesForSource(this.CompileSourceList);

-                    trackedOutputFiles.RemoveEntriesForSource(this.CompileSourceList);

-                    this.TrackedInputFiles.SaveTlog();

-                    trackedOutputFiles.SaveTlog();

-

-                    this.SkippedExecution = false;

-                }

-            }

-        }

-

-        protected bool SourceIsC(string sourceFilename)

-        {

-            string fileExt = Path.GetExtension(sourceFilename.ToString());

-

-            if (fileExt == ".c")

-                return true;

-            else

-                return false;

-        }

-

-        public override bool Execute()

-        {

-            bool returnResult = false;

-

-            try

-            {

-                m_XamlParser = new XamlParser(PropertiesFile);

-                m_toolname = Path.GetFileNameWithoutExtension(ToolName);

-                ValidateParameters();

-                CalcSourcesToCompile();

-

-                returnResult = base.Execute();

-

-                // Update tracker log files if execution occurred

-                //if (this.skippedExecution == false)

-                {

-                    CanonicalTrackedOutputFiles outputs = OutputWriteTrackerLog(CompileSourceList);

-                    ConstructReadTLog(CompileSourceList, outputs);

-                    OutputCommandTrackerLog(CompileSourceList);

-                }

-            }

-            finally

-            {

-

-            }

-

-            return returnResult;

-        }

-

-        protected List<ITaskItem> GetOutOfDateSourcesFromCommandLineChanges()

-        {

-            //get dictionary of source + command lines

-            IDictionary<string, string> dictionary = this.GenerateCommandLinesFromTlog();

-            List<ITaskItem> outOfDateSources = new List<ITaskItem>();

-

-            //add sources to out of date list if the tlog dictionary string do not match the generated command line string

-            StringBuilder currentCommandLine = new StringBuilder(GCCUtilities.s_CommandLineLength);

-            foreach (ITaskItem sourceItem in Sources)

-            {

-                currentCommandLine.Length = 0;

-

-                currentCommandLine.Append(GenerateCommandLineFromProps(sourceItem));

-                currentCommandLine.Append(" ");

-                currentCommandLine.Append(sourceItem.GetMetadata("FullPath").ToUpperInvariant());

-

-                string tlogCommandLine = null;

-                if (dictionary.TryGetValue(FileTracker.FormatRootingMarker(sourceItem), out tlogCommandLine))

-                {

-                    if ((tlogCommandLine == null) || !currentCommandLine.ToString().Equals(tlogCommandLine, StringComparison.Ordinal))

-                    {

-                        outOfDateSources.Add(sourceItem);

-                    }

-                }

-                else

-                {

-                    outOfDateSources.Add(sourceItem);

-                }

-            }

-            return outOfDateSources;

-        }

-

-        protected virtual void SetTrackerLogPaths()

-        {

-            if (this.TLogCommandFile == null)

-            {

-                string commandFile = Path.Combine(this.TlogDirectory, this.CommandTLogFilename);

-                this.TLogCommandFile = new TaskItem(commandFile);

-            }

-

-            if (this.TLogReadFiles == null)

-            {

-                this.TLogReadFiles = new ITaskItem[this.ReadTLogFilenames.Length];

-                for (int n = 0; n < this.ReadTLogFilenames.Length; n++)

-                {

-                    string readFile = Path.Combine(this.TlogDirectory, this.ReadTLogFilenames[n]);

-                    this.TLogReadFiles[n] = new TaskItem(readFile);

-                }

-            }

-

-            if (this.TLogWriteFiles == null)

-            {

-                this.TLogWriteFiles = new ITaskItem[1];

-                string writeFile = Path.Combine(this.TlogDirectory, this.WriteTLogFilename);

-                this.TLogWriteFiles[0] = new TaskItem(writeFile);

-            }

-        }

-

-

-        //props

-        protected string CommandTLogFilename

-        {

-            get

-            {

-                return m_toolname + ".compile.command.1.tlog";

-            }

-        }

-

-        protected string[] ReadTLogFilenames

-        {

-            get

-            {

-                return new string[] { m_toolname + ".compile.read.1.tlog" };

-            }

-        }

-

-        [Output]

-        public bool SkippedExecution

-        {

-            get

-            {

-                return this.skippedExecution;

-            }

-            set

-            {

-                this.skippedExecution = value;

-            }

-        }

-

-        public ITaskItem TLogCommandFile

-        {

-            get

-            {

-                return this.tlogCommandFile;

-            }

-            set

-            {

-                this.tlogCommandFile = value;

-            }

-        }

-

-        protected string TlogDirectory

-        {

-            get

-            {

-                if (this.TrackerLogDirectory != null)

-                {

-                    return this.TrackerLogDirectory;

-                }

-                return string.Empty;

-            }

-        }

-

-        public bool MinimalRebuildFromTracking

-        {

-            get

-            {

-                return this.minimalRebuildFromTracking;

-            }

-            set

-            {

-                this.minimalRebuildFromTracking = value;

-            }

-        }

-

-

-        public ITaskItem[] TLogReadFiles

-        {

-            get

-            {

-                return this.tlogReadFiles;

-            }

-            set

-            {

-                this.tlogReadFiles = value;

-            }

-        }

-

-        public ITaskItem[] ExcludedInputPaths

-        {

-            get

-            {

-                return this.excludedInputPaths;

-            }

-            set

-            {

-                this.excludedInputPaths = value;

-            }

-        }

-

-

-        public ITaskItem[] TLogWriteFiles

-        {

-            get

-            {

-                return this.tlogWriteFiles;

-            }

-            set

-            {

-                this.tlogWriteFiles = value;

-            }

-        }

-

-        protected string WriteTLogFilename

-        {

-            get

-            {

-                return m_toolname + ".compile.write.1.tlog";

-            }

-        }

-        

-        public bool TrackFileAccess

-        {

-            get

-            {

-                return this.trackFileAccess;

-            }

-            set

-            {

-                this.trackFileAccess = value;

-            }

-        }

-

-        protected CanonicalTrackedInputFiles TrackedInputFiles

-        {

-            get

-            {

-                return this.trackedInputFiles;

-            }

-            set

-            {

-                this.trackedInputFiles = value;

-            }

-        }

-

-        [Output]

-        public ITaskItem[] CompileSourceList

-        {

-            get

-            {

-                return this.compileSourceList;

-            }

-            set

-            {

-                this.compileSourceList = value;

-            }

-        }

-

-        protected override string ToolName

-        {

-            get

-            {

-                return NaCLCompilerPath;

-            }

-        }

-

-        protected override Encoding ResponseFileEncoding

-        {

-            get

-            {

-                return Encoding.ASCII;

-            }

-        }

-    }

+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+using System.Diagnostics;
+
+namespace NaCl.Build.CPPTasks
+{
+    public class NaClCompile : ToolTask
+    {
+        private XamlParser m_XamlParser;
+        private ITaskItem[] excludedInputPaths;
+        private ITaskItem[] tlogReadFiles;
+        private ITaskItem tlogCommandFile;
+        private ITaskItem[] tlogWriteFiles;
+        private CanonicalTrackedInputFiles trackedInputFiles;
+        private bool skippedExecution;
+        private ITaskItem[] compileSourceList;
+        public bool BuildingInIDE { get; set; }
+        private string m_toolname;
+        private bool trackFileAccess;
+        private bool minimalRebuildFromTracking;
+        private string pathToLog;
+
+        [Required]
+        public string PropertiesFile { get; set; }
+
+        [Required]
+        public ITaskItem[] Sources { get; set; }
+
+        [Required]
+        public string NaCLCompilerPath { get; set; }
+
+        [Required]
+        public string OutputCommandLine { get; set; }
+
+        [Required]
+        public string TrackerLogDirectory { get; set; }
+
+
+        protected override string GenerateFullPathToTool() { return ToolName; }
+
+        public NaClCompile()
+            : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", Assembly.GetExecutingAssembly()))
+        {
+            this.pathToLog = string.Empty;
+            this.EnvironmentVariables = new string []{"CYGWIN=nodosfilewarning", "LC_CTYPE=C"};
+        }
+
+        protected IDictionary<string, string> GenerateCommandLinesFromTlog()
+        {
+            IDictionary<string, string> cmdLineDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+            string tlogFilename = this.TLogCommandFile.GetMetadata("FullPath");
+            if (File.Exists(tlogFilename))
+            {
+                using (StreamReader reader = File.OpenText(tlogFilename))
+                {
+                    string filename = string.Empty;
+                    for (string lineStr = reader.ReadLine(); lineStr != null; lineStr = reader.ReadLine())
+                    {
+                        if (lineStr.Length == 0 ||
+                            (lineStr[0] == '^' && lineStr.Length == 1))
+                        {
+                            Log.LogMessage(MessageImportance.High, "Invalid line in command tlog");
+                            break;
+                        }
+                        else if (lineStr[0] == '^')
+                        {
+                            filename = lineStr.Substring(1);
+                        }
+                        else
+                        {
+                            cmdLineDictionary[filename] = lineStr;
+                        }
+                    }
+                }
+            }
+            return cmdLineDictionary;
+        }
+
+        protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
+        {
+            base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(singleLine), messageImportance);
+        }
+
+        private void ConstructReadTLog(ITaskItem[] compiledSources, CanonicalTrackedOutputFiles outputs)
+        {
+            string trackerPath = Path.GetFullPath(TlogDirectory + ReadTLogFilenames[0]);
+
+            //save tlog for sources not compiled during this execution
+            TaskItem readTrackerItem = new TaskItem(trackerPath);
+            CanonicalTrackedInputFiles files = new CanonicalTrackedInputFiles(new TaskItem[] { readTrackerItem }, Sources, outputs, false, false);
+            files.RemoveEntriesForSource(compiledSources);
+            files.SaveTlog();
+
+            //add tlog information for compiled sources
+            using (StreamWriter writer = new StreamWriter(trackerPath, true, Encoding.Unicode))
+            {
+                foreach (ITaskItem source in compiledSources)
+                {
+                    string sourcePath = Path.GetFullPath(source.ItemSpec).ToUpperInvariant();
+
+                    string objectFilePath = Path.GetFullPath(source.GetMetadata("ObjectFileName"));
+                    string depFilePath = Path.ChangeExtension(objectFilePath, ".d");
+
+                    try
+                    {
+                        if (File.Exists(depFilePath) == false)
+                        {
+                            Log.LogMessage(MessageImportance.High, depFilePath + " not found");
+                        }
+                        else
+                        {
+                            writer.WriteLine("^" + sourcePath);
+                            DependencyParser parser = new DependencyParser(depFilePath);
+                            
+                            foreach (string filename in parser.Dependencies)
+                            {
+                                //source itself not required
+                                if (filename == sourcePath)
+                                    continue;
+
+                                if (File.Exists(filename) == false)
+                                {
+                                    Log.LogMessage(MessageImportance.High, "File " + sourcePath + " is missing dependency " + filename);
+                                }
+
+                                writer.WriteLine(filename);
+                            }
+
+                            //remove d file
+                            try
+                            {
+                                File.Delete(depFilePath);
+                            }
+                            finally
+                            {
+
+                            }
+                        }
+
+                    }
+                    catch (Exception)
+                    {
+                        Log.LogError("Failed to update " + readTrackerItem + " for " + sourcePath);
+                    }
+                }
+            }
+        }
+
+        private CanonicalTrackedOutputFiles OutputWriteTrackerLog(ITaskItem[] compiledSources)
+        {
+            string path = Path.Combine(TlogDirectory, WriteTLogFilename);
+            TaskItem item = new TaskItem(path);
+            CanonicalTrackedOutputFiles trackedFiles = new CanonicalTrackedOutputFiles(new TaskItem[] { item });
+
+            foreach (ITaskItem sourceItem in compiledSources)
+            {
+                //remove this entry associated with compiled source which is about to be recomputed
+                trackedFiles.RemoveEntriesForSource(sourceItem);
+
+                //add entry with updated information
+                trackedFiles.AddComputedOutputForSourceRoot( Path.GetFullPath(sourceItem.ItemSpec).ToUpperInvariant(), 
+                                                             Path.GetFullPath(sourceItem.GetMetadata("ObjectFileName")).ToUpperInvariant());
+            }
+
+            //output tlog
+            trackedFiles.SaveTlog();
+
+            return trackedFiles;
+        }
+
+        private void OutputCommandTrackerLog(ITaskItem[] compiledSources)
+        {
+            IDictionary<string, string> commandLines = GenerateCommandLinesFromTlog();
+
+            //
+            if (compiledSources != null)
+            {
+                foreach (ITaskItem source in compiledSources)
+                {
+                    string rmSource = FileTracker.FormatRootingMarker(source);
+                    commandLines[rmSource] = GenerateCommandLineFromProps(source) + " " + source.GetMetadata("FullPath").ToUpperInvariant();
+                }
+            }
+
+            //write tlog
+            using (StreamWriter writer = new StreamWriter(this.TLogCommandFile.GetMetadata("FullPath"), false, Encoding.Unicode))
+            {
+                foreach (KeyValuePair<string, string> p in commandLines)
+                {
+                    string keyLine = "^" + p.Key;
+                    writer.WriteLine(keyLine);
+                    writer.WriteLine(p.Value);
+                }
+            }
+        }
+
+        protected string GenerateCommandLineFromProps(ITaskItem sourceFile)
+        {
+            StringBuilder commandLine = new StringBuilder(GCCUtilities.s_CommandLineLength);
+
+            if (sourceFile != null)
+            {
+                string sourcePath = GCCUtilities.Convert_Path_Windows_To_Posix(sourceFile.ToString());
+
+                // Remove rtti items as they are not relevant in C compilation and will produce warnings
+                if (SourceIsC(sourceFile.ToString()))
+                {
+                    commandLine.Replace("-fno-rtti", "");
+                    commandLine.Replace("-frtti", "");
+                }
+
+                //build command line from components and add required switches
+                string props = m_XamlParser.Parse(sourceFile);
+                commandLine.Append(props);
+                commandLine.Append(" -MD -c ");
+                commandLine.Append(sourcePath);
+
+            }
+
+            return commandLine.ToString();
+        }
+
+        protected ITaskItem[] MergeOutOfDateSources(ITaskItem[] outOfDateSourcesFromTracking, List<ITaskItem> outOfDateSourcesFromCommandLineChanges)
+        {
+            List<ITaskItem> mergedSources = new List<ITaskItem>(outOfDateSourcesFromTracking);
+
+            foreach (ITaskItem item in outOfDateSourcesFromCommandLineChanges)
+            {
+                if (!mergedSources.Contains(item))
+                {
+                    mergedSources.Add(item);
+                }
+            }
+
+            return mergedSources.ToArray();
+        }
+
+        protected bool ForcedRebuildRequired()
+        {
+            string tlogCommandPath = null;
+
+            try
+            {
+                tlogCommandPath = this.TLogCommandFile.GetMetadata("FullPath");
+            }
+            catch (Exception exception)
+            {
+                if (exception is InvalidOperationException || exception is NullReferenceException)
+                    return true;
+                else
+                    throw;
+            }
+
+            //if command tlog file does not exist then force rebuild is required
+            if (File.Exists(tlogCommandPath) == false)
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        private int Compile(string pathToTool)
+        {
+            int returnCode = 0;
+
+            foreach (ITaskItem sourceFileItem in CompileSourceList)
+            {
+                try
+                {
+                    string commandLine = GenerateCommandLineFromProps(sourceFileItem);
+
+                    base.Log.LogMessageFromText(Path.GetFileName(sourceFileItem.ToString()), MessageImportance.High);
+
+                    if (OutputCommandLine == "true")
+                    {
+                        string logMessage = pathToTool + " " + commandLine;
+                        Log.LogMessageFromText(logMessage, MessageImportance.High);
+                    }
+                    
+
+                    // compile
+                    returnCode = base.ExecuteTool(pathToTool, commandLine, string.Empty);
+                }
+                catch (Exception)
+                {
+                    returnCode = base.ExitCode;
+                }
+
+                //abort if an error was encountered
+                if (returnCode != 0)
+                {
+                    return returnCode;
+                }
+            }
+            return returnCode;
+        }
+
+        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
+        {
+            if (File.Exists(pathToTool) == false)
+            {
+                base.Log.LogMessageFromText("Unable to find NaCL compiler: " + pathToTool, MessageImportance.High);
+                return -1;
+            }
+
+            int returnCode = -1;
+
+            try
+            {
+                returnCode = Compile(pathToTool);
+            }
+            finally
+            {
+
+            }
+            return returnCode;
+        }
+
+        protected override bool SkipTaskExecution()
+        {
+            return this.skippedExecution;
+        }
+
+        protected void CalcSourcesToCompile()
+        {
+            if (this.TrackFileAccess || this.MinimalRebuildFromTracking)
+            {
+                this.SetTrackerLogPaths();
+            }
+
+            //check if full recompile is required otherwise perform incremental
+            if (this.ForcedRebuildRequired() || this.MinimalRebuildFromTracking == false)
+            {
+                this.CompileSourceList = this.Sources;
+                if ((this.CompileSourceList == null) || (this.CompileSourceList.Length == 0))
+                {
+                    this.SkippedExecution = true;
+                }
+            }
+            else
+            {
+                //retrieve list of sources out of date due to command line changes
+                List<ITaskItem> outOfDateSourcesFromCommandLineChanges = this.GetOutOfDateSourcesFromCommandLineChanges();
+
+                //retrieve sources out of date due to tracking
+                CanonicalTrackedOutputFiles trackedOutputFiles = new CanonicalTrackedOutputFiles(this, this.TLogWriteFiles);
+                this.TrackedInputFiles = new CanonicalTrackedInputFiles(this, this.TLogReadFiles, this.Sources, this.ExcludedInputPaths, trackedOutputFiles, true, false);
+                ITaskItem[] outOfDateSourcesFromTracking = this.TrackedInputFiles.ComputeSourcesNeedingCompilation();
+
+                //merge out of date lists
+                this.CompileSourceList = this.MergeOutOfDateSources(outOfDateSourcesFromTracking, outOfDateSourcesFromCommandLineChanges);
+
+                if (this.CompileSourceList.Length == 0)
+                {
+                    this.SkippedExecution = true;
+                }
+                else
+                {
+                    //remove sources to compile from tracked file list
+                    this.TrackedInputFiles.RemoveEntriesForSource(this.CompileSourceList);
+                    trackedOutputFiles.RemoveEntriesForSource(this.CompileSourceList);
+                    this.TrackedInputFiles.SaveTlog();
+                    trackedOutputFiles.SaveTlog();
+
+                    this.SkippedExecution = false;
+                }
+            }
+        }
+
+        protected bool SourceIsC(string sourceFilename)
+        {
+            string fileExt = Path.GetExtension(sourceFilename.ToString());
+
+            if (fileExt == ".c")
+                return true;
+            else
+                return false;
+        }
+
+        public override bool Execute()
+        {
+            bool returnResult = false;
+
+            try
+            {
+                m_XamlParser = new XamlParser(PropertiesFile);
+                m_toolname = Path.GetFileNameWithoutExtension(ToolName);
+                ValidateParameters();
+                CalcSourcesToCompile();
+
+                returnResult = base.Execute();
+
+                // Update tracker log files if execution occurred
+                //if (this.skippedExecution == false)
+                {
+                    CanonicalTrackedOutputFiles outputs = OutputWriteTrackerLog(CompileSourceList);
+                    ConstructReadTLog(CompileSourceList, outputs);
+                    OutputCommandTrackerLog(CompileSourceList);
+                }
+            }
+            finally
+            {
+
+            }
+
+            return returnResult;
+        }
+
+        protected List<ITaskItem> GetOutOfDateSourcesFromCommandLineChanges()
+        {
+            //get dictionary of source + command lines
+            IDictionary<string, string> dictionary = this.GenerateCommandLinesFromTlog();
+            List<ITaskItem> outOfDateSources = new List<ITaskItem>();
+
+            //add sources to out of date list if the tlog dictionary string do not match the generated command line string
+            StringBuilder currentCommandLine = new StringBuilder(GCCUtilities.s_CommandLineLength);
+            foreach (ITaskItem sourceItem in Sources)
+            {
+                currentCommandLine.Length = 0;
+
+                currentCommandLine.Append(GenerateCommandLineFromProps(sourceItem));
+                currentCommandLine.Append(" ");
+                currentCommandLine.Append(sourceItem.GetMetadata("FullPath").ToUpperInvariant());
+
+                string tlogCommandLine = null;
+                if (dictionary.TryGetValue(FileTracker.FormatRootingMarker(sourceItem), out tlogCommandLine))
+                {
+                    if ((tlogCommandLine == null) || !currentCommandLine.ToString().Equals(tlogCommandLine, StringComparison.Ordinal))
+                    {
+                        outOfDateSources.Add(sourceItem);
+                    }
+                }
+                else
+                {
+                    outOfDateSources.Add(sourceItem);
+                }
+            }
+            return outOfDateSources;
+        }
+
+        protected virtual void SetTrackerLogPaths()
+        {
+            if (this.TLogCommandFile == null)
+            {
+                string commandFile = Path.Combine(this.TlogDirectory, this.CommandTLogFilename);
+                this.TLogCommandFile = new TaskItem(commandFile);
+            }
+
+            if (this.TLogReadFiles == null)
+            {
+                this.TLogReadFiles = new ITaskItem[this.ReadTLogFilenames.Length];
+                for (int n = 0; n < this.ReadTLogFilenames.Length; n++)
+                {
+                    string readFile = Path.Combine(this.TlogDirectory, this.ReadTLogFilenames[n]);
+                    this.TLogReadFiles[n] = new TaskItem(readFile);
+                }
+            }
+
+            if (this.TLogWriteFiles == null)
+            {
+                this.TLogWriteFiles = new ITaskItem[1];
+                string writeFile = Path.Combine(this.TlogDirectory, this.WriteTLogFilename);
+                this.TLogWriteFiles[0] = new TaskItem(writeFile);
+            }
+        }
+
+
+        //props
+        protected string CommandTLogFilename
+        {
+            get
+            {
+                return m_toolname + ".compile.command.1.tlog";
+            }
+        }
+
+        protected string[] ReadTLogFilenames
+        {
+            get
+            {
+                return new string[] { m_toolname + ".compile.read.1.tlog" };
+            }
+        }
+
+        [Output]
+        public bool SkippedExecution
+        {
+            get
+            {
+                return this.skippedExecution;
+            }
+            set
+            {
+                this.skippedExecution = value;
+            }
+        }
+
+        public ITaskItem TLogCommandFile
+        {
+            get
+            {
+                return this.tlogCommandFile;
+            }
+            set
+            {
+                this.tlogCommandFile = value;
+            }
+        }
+
+        protected string TlogDirectory
+        {
+            get
+            {
+                if (this.TrackerLogDirectory != null)
+                {
+                    return this.TrackerLogDirectory;
+                }
+                return string.Empty;
+            }
+        }
+
+        public bool MinimalRebuildFromTracking
+        {
+            get
+            {
+                return this.minimalRebuildFromTracking;
+            }
+            set
+            {
+                this.minimalRebuildFromTracking = value;
+            }
+        }
+
+
+        public ITaskItem[] TLogReadFiles
+        {
+            get
+            {
+                return this.tlogReadFiles;
+            }
+            set
+            {
+                this.tlogReadFiles = value;
+            }
+        }
+
+        public ITaskItem[] ExcludedInputPaths
+        {
+            get
+            {
+                return this.excludedInputPaths;
+            }
+            set
+            {
+                this.excludedInputPaths = value;
+            }
+        }
+
+
+        public ITaskItem[] TLogWriteFiles
+        {
+            get
+            {
+                return this.tlogWriteFiles;
+            }
+            set
+            {
+                this.tlogWriteFiles = value;
+            }
+        }
+
+        protected string WriteTLogFilename
+        {
+            get
+            {
+                return m_toolname + ".compile.write.1.tlog";
+            }
+        }
+        
+        public bool TrackFileAccess
+        {
+            get
+            {
+                return this.trackFileAccess;
+            }
+            set
+            {
+                this.trackFileAccess = value;
+            }
+        }
+
+        protected CanonicalTrackedInputFiles TrackedInputFiles
+        {
+            get
+            {
+                return this.trackedInputFiles;
+            }
+            set
+            {
+                this.trackedInputFiles = value;
+            }
+        }
+
+        [Output]
+        public ITaskItem[] CompileSourceList
+        {
+            get
+            {
+                return this.compileSourceList;
+            }
+            set
+            {
+                this.compileSourceList = value;
+            }
+        }
+
+        protected override string ToolName
+        {
+            get
+            {
+                return NaCLCompilerPath;
+            }
+        }
+
+        protected override Encoding ResponseFileEncoding
+        {
+            get
+            {
+                return Encoding.ASCII;
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/NaCl.Build.CPPTasks/NaClLib.cs b/NaCl.Build.CPPTasks/NaClLib.cs
index bd32bf0..2c732ee 100644
--- a/NaCl.Build.CPPTasks/NaClLib.cs
+++ b/NaCl.Build.CPPTasks/NaClLib.cs
@@ -1,161 +1,161 @@
-

-using System;

-using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-using System.Collections;

-using System.IO;

-using System.Reflection;

-using System.Resources;

-using System.Text.RegularExpressions;

-using System.Diagnostics;

-

-using Microsoft.Build.Framework;

-using Microsoft.Build.CPPTasks;

-using Microsoft.Build.Utilities;

-

-namespace NaCl.Build.CPPTasks

-{

-    public class NaClLib : TrackedVCToolTask

-    {

-        public bool BuildingInIDE { get; set; }

-

-        [Required]

-        public string LibrarianToolPath { get; set; }

-

-        [Required]

-        public string PropertiesFile { get; set; }

-

-        [Required]

-        public virtual string OutputFile { get; set; }

-

-        [Required]

-        public string OutputCommandLine { get; set; }

-

-        [Required]

-        public virtual ITaskItem[] Sources { get; set; }

-        

-

-        public NaClLib()

-            : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", Assembly.GetExecutingAssembly()))

-        {

-          this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning", "LC_CTYPE=C" };

-        }

-

-        protected override string GenerateResponseFileCommands()

-        {

-            StringBuilder responseFileCmds = new StringBuilder(GCCUtilities.s_CommandLineLength);

-            responseFileCmds.Append("rcs ");

-            responseFileCmds.Append(GCCUtilities.Convert_Path_Windows_To_Posix(OutputFile));

-

-            foreach (ITaskItem item in Sources)

-            {

-                responseFileCmds.Append(" ");

-                responseFileCmds.Append(GCCUtilities.Convert_Path_Windows_To_Posix(item.ToString()));

-            }

-            return responseFileCmds.ToString();

-        }

-

-        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)

-        {

-            if (OutputCommandLine == "true")

-            {

-                Log.LogMessage(MessageImportance.High, pathToTool + "  " + responseFileCommands);

-            }

-

-            return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);

-        }         

-

-

-

-        public virtual string PlatformToolset

-        {

-            get

-            {

-                return "GCC";

-            }

-        }

-

-        protected override bool MaintainCompositeRootingMarkers

-        {

-            get

-            {

-                return true;

-            }

-        }

-

-        protected override ITaskItem[] TrackedInputFiles

-        {

-            get

-            {

-                return Sources;

-            }

-        }

-

-

-        protected override Encoding ResponseFileEncoding

-        {

-            get

-            {

-                return Encoding.ASCII;

-            }

-        }

-

-        protected override string ToolName

-        {

-            get

-            {

-                return LibrarianToolPath;

-            }

-        }

-

-        protected override string TrackerIntermediateDirectory

-        {

-            get

-            {

-                if (this.TrackerLogDirectory != null)

-                {

-                    return this.TrackerLogDirectory;

-                }

-                else

-                {

-                    return string.Empty;

-                }

-            }

-        }

-

-        protected override string CommandTLogName

-        {

-            get

-            {

-                return "default.link.command.tlog";

-            }

-        }

-

-        protected override string[] ReadTLogNames

-        {

-            get

-            {

-                return new string[] 

-                { 

-                    "default.link.read.tlog"

-                };

-            }

-        }

-

-        protected override string[] WriteTLogNames

-        {

-            get

-            {

-                return new string[] 

-                { 

-                    "default.link.write.tlog"

-                };

-            }

-        }

-

-        public string TrackerLogDirectory { get; set; }

-    }

-

-

-}

+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using System.Text.RegularExpressions;
+using System.Diagnostics;
+
+using Microsoft.Build.Framework;
+using Microsoft.Build.CPPTasks;
+using Microsoft.Build.Utilities;
+
+namespace NaCl.Build.CPPTasks
+{
+    public class NaClLib : TrackedVCToolTask
+    {
+        public bool BuildingInIDE { get; set; }
+
+        [Required]
+        public string LibrarianToolPath { get; set; }
+
+        [Required]
+        public string PropertiesFile { get; set; }
+
+        [Required]
+        public virtual string OutputFile { get; set; }
+
+        [Required]
+        public string OutputCommandLine { get; set; }
+
+        [Required]
+        public virtual ITaskItem[] Sources { get; set; }
+        
+
+        public NaClLib()
+            : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", Assembly.GetExecutingAssembly()))
+        {
+          this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning", "LC_CTYPE=C" };
+        }
+
+        protected override string GenerateResponseFileCommands()
+        {
+            StringBuilder responseFileCmds = new StringBuilder(GCCUtilities.s_CommandLineLength);
+            responseFileCmds.Append("rcs ");
+            responseFileCmds.Append(GCCUtilities.Convert_Path_Windows_To_Posix(OutputFile));
+
+            foreach (ITaskItem item in Sources)
+            {
+                responseFileCmds.Append(" ");
+                responseFileCmds.Append(GCCUtilities.Convert_Path_Windows_To_Posix(item.ToString()));
+            }
+            return responseFileCmds.ToString();
+        }
+
+        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
+        {
+            if (OutputCommandLine == "true")
+            {
+                Log.LogMessage(MessageImportance.High, pathToTool + "  " + responseFileCommands);
+            }
+
+            return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
+        }         
+
+
+
+        public virtual string PlatformToolset
+        {
+            get
+            {
+                return "GCC";
+            }
+        }
+
+        protected override bool MaintainCompositeRootingMarkers
+        {
+            get
+            {
+                return true;
+            }
+        }
+
+        protected override ITaskItem[] TrackedInputFiles
+        {
+            get
+            {
+                return Sources;
+            }
+        }
+
+
+        protected override Encoding ResponseFileEncoding
+        {
+            get
+            {
+                return Encoding.ASCII;
+            }
+        }
+
+        protected override string ToolName
+        {
+            get
+            {
+                return LibrarianToolPath;
+            }
+        }
+
+        protected override string TrackerIntermediateDirectory
+        {
+            get
+            {
+                if (this.TrackerLogDirectory != null)
+                {
+                    return this.TrackerLogDirectory;
+                }
+                else
+                {
+                    return string.Empty;
+                }
+            }
+        }
+
+        protected override string CommandTLogName
+        {
+            get
+            {
+                return "default.link.command.tlog";
+            }
+        }
+
+        protected override string[] ReadTLogNames
+        {
+            get
+            {
+                return new string[] 
+                { 
+                    "default.link.read.tlog"
+                };
+            }
+        }
+
+        protected override string[] WriteTLogNames
+        {
+            get
+            {
+                return new string[] 
+                { 
+                    "default.link.write.tlog"
+                };
+            }
+        }
+
+        public string TrackerLogDirectory { get; set; }
+    }
+
+
+}
diff --git a/NaCl.Build.CPPTasks/NaClLink.cs b/NaCl.Build.CPPTasks/NaClLink.cs
index a55543e..7a0ee54 100644
--- a/NaCl.Build.CPPTasks/NaClLink.cs
+++ b/NaCl.Build.CPPTasks/NaClLink.cs
@@ -1,195 +1,195 @@
-

-using System;

-using System.IO;

-using System.Resources;

-using System.Reflection;

-using System.Text;

-using Microsoft.Build.Framework;

-using Microsoft.Build.CPPTasks;

-

-

-namespace NaCl.Build.CPPTasks

-{

-    public class NaClLink : TrackedVCToolTask

-	{

-        private XamlParser m_XamlParser;

-

-        public bool BuildingInIDE { get; set; }

-

-        [Required]

-        public string OutputCommandLine { get; set; }

-

-        [Required]

-        public string NaClLinkerPath { get; set; }

-

-        [Required]

-        public virtual string OutputFile { get; set; }

-

-        [Required]

-        public string PropertiesFile { get; set; }

-

-        [Required]

-        public virtual ITaskItem[] Sources { get; set; }

-

-        [Required]

-        public string ConfigurationType { get; set; }

-

-        public NaClLink()

-            : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", Assembly.GetExecutingAssembly()))

-        {

-          this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning", "LC_CTYPE=C" };

-        }

-

-        protected override string CommandTLogName

-        {

-            get

-            {

-                return "default.link.command.tlog";

-            }

-        }

-

-        protected override string[] ReadTLogNames

-        {

-            get

-            {

-                return new string[] { 

-                    "default.link.read.tlog"

-                };

-            }

-        }

-

-        protected override string[] WriteTLogNames

-        {

-            get

-            {

-                return new string[] { 

-                    "default.link.write.tlog"

-                };

-            }

-        }

-

-        protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)

-        {

-            base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(singleLine), messageImportance);

-        }

-

-        protected override string GenerateResponseFileCommands()

-        {

-            StringBuilder responseFileCmds = new StringBuilder(GCCUtilities.s_CommandLineLength);

-

-            foreach (ITaskItem sourceFile in Sources)

-            {

-                responseFileCmds.Append(GCCUtilities.Convert_Path_Windows_To_Posix(sourceFile.GetMetadata("Identity")));

-                responseFileCmds.Append(" ");

-            }

-

-            responseFileCmds.Append(m_XamlParser.Parse(Sources[0]));

-

-            return responseFileCmds.ToString();

-        }

-

-        public override bool Execute()

-        {

-            bool returnResult = false;

-

-            try

-            {

-                m_XamlParser = new XamlParser(PropertiesFile);

-

-                returnResult = base.Execute();

-            }

-            finally

-            {

-

-            }

-

-            return returnResult;

-        }

-

-        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)

-        {

-            if (OutputCommandLine == "true")

-            {

-                Log.LogMessage(MessageImportance.High, pathToTool + "  " + responseFileCommands);

-            }

-

-            return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);

-        }

-

-        protected override void PostProcessSwitchList()

-        {

-            //skip default behavior

-        }

-

-        protected override string GenerateFullPathToTool()

-        {

-            return this.ToolName;

-        }

-

-        protected override string TrackerIntermediateDirectory

-        {

-            get

-            {

-                if (this.TrackerLogDirectory != null)

-                {

-                    return this.TrackerLogDirectory;

-                }

-

-                return string.Empty;

-            }

-        }

-

-        protected override Encoding ResponseFileEncoding

-        {

-            get

-            {

-                return Encoding.ASCII;

-            }

-        }

-

-        protected override ITaskItem[] TrackedInputFiles

-        {

-            get

-            {

-                return this.Sources;

-            }

-        }

-

-        protected override bool MaintainCompositeRootingMarkers

-        {

-            get

-            {

-                return true;

-            }

-

-        }

-

-        protected override string ToolName

-        {

-            get

-            {

-                return NaClLinkerPath;

-            }

-        }

-

-        public override bool AttributeFileTracking

-        {

-            get

-            {

-                return true;

-            }

-        }     

-

-        public virtual string PlatformToolset

-        {

-            get

-            {

-                return "GCC";

-            }

-            set

-            {}

-        }  

-

-        public string TrackerLogDirectory { get; set; }

-	}

-}

+
+using System;
+using System.IO;
+using System.Resources;
+using System.Reflection;
+using System.Text;
+using Microsoft.Build.Framework;
+using Microsoft.Build.CPPTasks;
+
+
+namespace NaCl.Build.CPPTasks
+{
+    public class NaClLink : TrackedVCToolTask
+	{
+        private XamlParser m_XamlParser;
+
+        public bool BuildingInIDE { get; set; }
+
+        [Required]
+        public string OutputCommandLine { get; set; }
+
+        [Required]
+        public string NaClLinkerPath { get; set; }
+
+        [Required]
+        public virtual string OutputFile { get; set; }
+
+        [Required]
+        public string PropertiesFile { get; set; }
+
+        [Required]
+        public virtual ITaskItem[] Sources { get; set; }
+
+        [Required]
+        public string ConfigurationType { get; set; }
+
+        public NaClLink()
+            : base(new ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", Assembly.GetExecutingAssembly()))
+        {
+          this.EnvironmentVariables = new string[] { "CYGWIN=nodosfilewarning", "LC_CTYPE=C" };
+        }
+
+        protected override string CommandTLogName
+        {
+            get
+            {
+                return "default.link.command.tlog";
+            }
+        }
+
+        protected override string[] ReadTLogNames
+        {
+            get
+            {
+                return new string[] { 
+                    "default.link.read.tlog"
+                };
+            }
+        }
+
+        protected override string[] WriteTLogNames
+        {
+            get
+            {
+                return new string[] { 
+                    "default.link.write.tlog"
+                };
+            }
+        }
+
+        protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
+        {
+            base.LogEventsFromTextOutput(GCCUtilities.Convert_Output_GCC_to_VS(singleLine), messageImportance);
+        }
+
+        protected override string GenerateResponseFileCommands()
+        {
+            StringBuilder responseFileCmds = new StringBuilder(GCCUtilities.s_CommandLineLength);
+
+            foreach (ITaskItem sourceFile in Sources)
+            {
+                responseFileCmds.Append(GCCUtilities.Convert_Path_Windows_To_Posix(sourceFile.GetMetadata("Identity")));
+                responseFileCmds.Append(" ");
+            }
+
+            responseFileCmds.Append(m_XamlParser.Parse(Sources[0]));
+
+            return responseFileCmds.ToString();
+        }
+
+        public override bool Execute()
+        {
+            bool returnResult = false;
+
+            try
+            {
+                m_XamlParser = new XamlParser(PropertiesFile);
+
+                returnResult = base.Execute();
+            }
+            finally
+            {
+
+            }
+
+            return returnResult;
+        }
+
+        protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
+        {
+            if (OutputCommandLine == "true")
+            {
+                Log.LogMessage(MessageImportance.High, pathToTool + "  " + responseFileCommands);
+            }
+
+            return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
+        }
+
+        protected override void PostProcessSwitchList()
+        {
+            //skip default behavior
+        }
+
+        protected override string GenerateFullPathToTool()
+        {
+            return this.ToolName;
+        }
+
+        protected override string TrackerIntermediateDirectory
+        {
+            get
+            {
+                if (this.TrackerLogDirectory != null)
+                {
+                    return this.TrackerLogDirectory;
+                }
+
+                return string.Empty;
+            }
+        }
+
+        protected override Encoding ResponseFileEncoding
+        {
+            get
+            {
+                return Encoding.ASCII;
+            }
+        }
+
+        protected override ITaskItem[] TrackedInputFiles
+        {
+            get
+            {
+                return this.Sources;
+            }
+        }
+
+        protected override bool MaintainCompositeRootingMarkers
+        {
+            get
+            {
+                return true;
+            }
+
+        }
+
+        protected override string ToolName
+        {
+            get
+            {
+                return NaClLinkerPath;
+            }
+        }
+
+        public override bool AttributeFileTracking
+        {
+            get
+            {
+                return true;
+            }
+        }     
+
+        public virtual string PlatformToolset
+        {
+            get
+            {
+                return "GCC";
+            }
+            set
+            {}
+        }  
+
+        public string TrackerLogDirectory { get; set; }
+	}
+}
diff --git a/NaCl.Build.CPPTasks/Properties/AssemblyInfo.cs b/NaCl.Build.CPPTasks/Properties/AssemblyInfo.cs
index f248fdd..71a3fea 100644
--- a/NaCl.Build.CPPTasks/Properties/AssemblyInfo.cs
+++ b/NaCl.Build.CPPTasks/Properties/AssemblyInfo.cs
@@ -1,38 +1,38 @@
-//CONVERTED - ENTIRE FILE

-

-using System.Reflection;

-using System.Runtime.CompilerServices;

-using System.Runtime.InteropServices;

-

-// General Information about an assembly is controlled through the following 

-// set of attributes. Change these attribute values to modify the information

-// associated with an assembly.

-[assembly: AssemblyTitle("NaCl.Build.CPPTasks")]

-[assembly: AssemblyDescription("")]

-[assembly: AssemblyConfiguration("")]

-[assembly: AssemblyCompany("Google Inc.")]

-[assembly: AssemblyProduct("NaCl.Build.CPPTasks")]

-[assembly: AssemblyCopyright("Copyright © 2012 The Chromium Authors")]

-[assembly: AssemblyTrademark("")]

-[assembly: AssemblyCulture("")]

-

-// Setting ComVisible to false makes the types in this assembly not visible 

-// to COM components.  If you need to access a type in this assembly from 

-// COM, set the ComVisible attribute to true on that type.

-[assembly: ComVisible(false)]

-

-// The following GUID is for the ID of the typelib if this project is exposed to COM

-[assembly: Guid("a17d894a-0fe8-46e4-8715-60f815bc103d")]

-

-// Version information for an assembly consists of the following four values:

-//

-//      Major Version

-//      Minor Version 

-//      Build Number

-//      Revision

-//

-// You can specify all the values or you can default the Build and Revision Numbers 

-// by using the '*' as shown below:

-// [assembly: AssemblyVersion("1.0.*")]

-[assembly: AssemblyVersion("1.0.0.0")]

-[assembly: AssemblyFileVersion("1.0.0.0")]

+//CONVERTED - ENTIRE FILE
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("NaCl.Build.CPPTasks")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Google Inc.")]
+[assembly: AssemblyProduct("NaCl.Build.CPPTasks")]
+[assembly: AssemblyCopyright("Copyright © 2012 The Chromium Authors")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a17d894a-0fe8-46e4-8715-60f815bc103d")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/NaCl.Build.CPPTasks/Properties/Resources.Designer.cs b/NaCl.Build.CPPTasks/Properties/Resources.Designer.cs
index 31cd155..c419c72 100644
--- a/NaCl.Build.CPPTasks/Properties/Resources.Designer.cs
+++ b/NaCl.Build.CPPTasks/Properties/Resources.Designer.cs
@@ -1,144 +1,144 @@
-//------------------------------------------------------------------------------

-// <auto-generated>

-//     This code was generated by a tool.

-//     Runtime Version:4.0.30319.269

-//

-//     Changes to this file may cause incorrect behavior and will be lost if

-//     the code is regenerated.

-// </auto-generated>

-//------------------------------------------------------------------------------

-

-namespace NaCl.Build.CPPTasks.Properties {

-    using System;

-    

-    

-    /// <summary>

-    ///   A strongly-typed resource class, for looking up localized strings, etc.

-    /// </summary>

-    // This class was auto-generated by the StronglyTypedResourceBuilder

-    // class via a tool like ResGen or Visual Studio.

-    // To add or remove a member, edit your .ResX file then rerun ResGen

-    // with the /str option, or rebuild your VS project.

-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]

-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

-    internal class Resources {

-        

-        private static global::System.Resources.ResourceManager resourceMan;

-        

-        private static global::System.Globalization.CultureInfo resourceCulture;

-        

-        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]

-        internal Resources() {

-        }

-        

-        /// <summary>

-        ///   Returns the cached ResourceManager instance used by this class.

-        /// </summary>

-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

-        internal static global::System.Resources.ResourceManager ResourceManager {

-            get {

-                if (object.ReferenceEquals(resourceMan, null)) {

-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", typeof(Resources).Assembly);

-                    resourceMan = temp;

-                }

-                return resourceMan;

-            }

-        }

-        

-        /// <summary>

-        ///   Overrides the current thread's CurrentUICulture property for all

-        ///   resource lookups using this strongly typed resource class.

-        /// </summary>

-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

-        internal static global::System.Globalization.CultureInfo Culture {

-            get {

-                return resourceCulture;

-            }

-            set {

-                resourceCulture = value;

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to # This file is automatically generated by vs-nacl.

-        ///# Do not modify this file -- YOUR CHANGES WILL BE ERASED!

-        ///#

-        ///# This file must *NOT* be checked in Version Control Systems,

-        ///# as it contains information specific to your local configuration.

-        ///

-        ///# location of the SDK. This is only used by Ant

-        ///# For customization when using a Version Control System, please read the

-        ///# header note.

-        ///sdk.dir={SDKDIR}.

-        /// </summary>

-        internal static string localproperties_ant_file {

-            get {

-                return ResourceManager.GetString("localproperties_ant_file", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Tracking command:.

-        /// </summary>

-        internal static string Native_TrackingCommandMessage {

-            get {

-                return ResourceManager.GetString("Native_TrackingCommandMessage", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to MSB8016: Can not turn on Unicode output for &quot;{0}&quot;. Some Unicode characters will be improperly displayed..

-        /// </summary>

-        internal static string TrackedVCToolTask_CreateUnicodeOutputPipeFailed {

-            get {

-                return ResourceManager.GetString("TrackedVCToolTask.CreateUnicodeOutputPipeFailed", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Forcing rebuild of all source files due to a change in the command line since the last build..

-        /// </summary>

-        internal static string TrackedVCToolTask_RebuildingAllSourcesCommandLineChanged {

-            get {

-                return ResourceManager.GetString("TrackedVCToolTask.RebuildingAllSourcesCommandLineChanged", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to MSB8014: Forcing a rebuild of all sources due to an error with the tracking logs. {0}.

-        /// </summary>

-        internal static string TrackedVCToolTask_RebuildingDueToInvalidTLog {

-            get {

-                return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLog", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to MSB8015: Forcing a rebuild of all source files due to the contents of &quot;{0}&quot; being invalid..

-        /// </summary>

-        internal static string TrackedVCToolTask_RebuildingDueToInvalidTLogContents {

-            get {

-                return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLogContents", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Forcing rebuild of all source files due to missing command tlog &quot;{0}&quot;..

-        /// </summary>

-        internal static string TrackedVCToolTask_RebuildingNoCommandTLog {

-            get {

-                return ResourceManager.GetString("TrackedVCToolTask.RebuildingNoCommandTLog", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Forcing rebuild of source file &quot;{0}&quot; due to a change in the command line since the last build..

-        /// </summary>

-        internal static string TrackedVCToolTask_RebuildingSourceCommandLineChanged {

-            get {

-                return ResourceManager.GetString("TrackedVCToolTask.RebuildingSourceCommandLineChanged", resourceCulture);

-            }

-        }

-    }

-}

+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.269
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace NaCl.Build.CPPTasks.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NaCl.Build.CPPTasks.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to # This file is automatically generated by vs-nacl.
+        ///# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+        ///#
+        ///# This file must *NOT* be checked in Version Control Systems,
+        ///# as it contains information specific to your local configuration.
+        ///
+        ///# location of the SDK. This is only used by Ant
+        ///# For customization when using a Version Control System, please read the
+        ///# header note.
+        ///sdk.dir={SDKDIR}.
+        /// </summary>
+        internal static string localproperties_ant_file {
+            get {
+                return ResourceManager.GetString("localproperties_ant_file", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Tracking command:.
+        /// </summary>
+        internal static string Native_TrackingCommandMessage {
+            get {
+                return ResourceManager.GetString("Native_TrackingCommandMessage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to MSB8016: Can not turn on Unicode output for &quot;{0}&quot;. Some Unicode characters will be improperly displayed..
+        /// </summary>
+        internal static string TrackedVCToolTask_CreateUnicodeOutputPipeFailed {
+            get {
+                return ResourceManager.GetString("TrackedVCToolTask.CreateUnicodeOutputPipeFailed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Forcing rebuild of all source files due to a change in the command line since the last build..
+        /// </summary>
+        internal static string TrackedVCToolTask_RebuildingAllSourcesCommandLineChanged {
+            get {
+                return ResourceManager.GetString("TrackedVCToolTask.RebuildingAllSourcesCommandLineChanged", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to MSB8014: Forcing a rebuild of all sources due to an error with the tracking logs. {0}.
+        /// </summary>
+        internal static string TrackedVCToolTask_RebuildingDueToInvalidTLog {
+            get {
+                return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLog", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to MSB8015: Forcing a rebuild of all source files due to the contents of &quot;{0}&quot; being invalid..
+        /// </summary>
+        internal static string TrackedVCToolTask_RebuildingDueToInvalidTLogContents {
+            get {
+                return ResourceManager.GetString("TrackedVCToolTask.RebuildingDueToInvalidTLogContents", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Forcing rebuild of all source files due to missing command tlog &quot;{0}&quot;..
+        /// </summary>
+        internal static string TrackedVCToolTask_RebuildingNoCommandTLog {
+            get {
+                return ResourceManager.GetString("TrackedVCToolTask.RebuildingNoCommandTLog", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Forcing rebuild of source file &quot;{0}&quot; due to a change in the command line since the last build..
+        /// </summary>
+        internal static string TrackedVCToolTask_RebuildingSourceCommandLineChanged {
+            get {
+                return ResourceManager.GetString("TrackedVCToolTask.RebuildingSourceCommandLineChanged", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/NaCl.Build.CPPTasks/XamlParser.cs b/NaCl.Build.CPPTasks/XamlParser.cs
index 099d4df..8acbc5f 100644
--- a/NaCl.Build.CPPTasks/XamlParser.cs
+++ b/NaCl.Build.CPPTasks/XamlParser.cs
@@ -1,152 +1,152 @@
-using System;

-using System.Collections.Generic;

-using System.Linq;

-using System.Text;

-

-using Microsoft.Build.Framework;

-using System.Xaml;

-using Microsoft.Build.Framework.XamlTypes;

-using Microsoft.Build.Utilities;

-

-namespace NaCl.Build.CPPTasks

-{

-    class XamlParser

-    {

-        public XamlParser(string path)

-        {

-            // load and store properties from xaml file

-            m_parsedBuildRule = (Rule)XamlServices.Load(path);

-

-            // NOTE: 

-            // There are MSBuild classes which support command line building, 

-            // argument switch encapsulation and more.  Code within VCToolTask, 

-            // a hidden interface, uses some these classes to generate command line 

-            // switches given project settings. As the VCToolTask class is a hidden 

-            // class and the MSBuild documentation is very sparse, we are going 

-            // with a small custom solution.  For reference see the 

-            // Microsoft.Build.Tasks.Xaml, Microsoft.Build.Framework.XamlTypes namespaces.

-

-            // move the properties to a property name keyed dictionary for faster lookup

-            ToolProperties = new Dictionary<string, PropertyWrapper>();

-            ToolProperties = m_parsedBuildRule.Properties.ToDictionary(x => x.Name, x => (new PropertyWrapper(x.GetType(), x)));

-

-            InitFunctionMap();

-        }

-

-        private void InitFunctionMap()

-        {

-            m_typeFunctionMap = new Dictionary<Type, Action<CommandLineBuilder, BaseProperty, string>>

-            {

-                { typeof(StringListProperty), GenerateArgumentStringList },

-                { typeof(StringProperty), GenerateArgumentString },

-                { typeof(IntProperty), GenerateArgumentString },

-                { typeof(BoolProperty), GenerateArgumentBool },

-                { typeof(EnumProperty), GenerateArgumentEnum }

-            };

-        }

-

-        public string Parse(ITaskItem taskItem)

-        {

-            CommandLineBuilder builder = new CommandLineBuilder();

-

-            foreach (string name in taskItem.MetadataNames)

-            {

-                string value = taskItem.GetMetadata(name);

-                AppendArgumentForProperty(builder, name, value);

-            }

-

-            string result = builder.ToString();

-            result = result.Replace('\\', '/'); // posix paths

-            return result;

-        }

-

-        private string AppendArgumentForProperty(CommandLineBuilder builder, string name, string value)

-        {

-            PropertyWrapper current;

-            ToolProperties.TryGetValue(name, out current);

-            if (current != null && value.Length > 0)

-            {

-                // call appropriate function for type

-                m_typeFunctionMap[current.PropertyType](builder, current.Property, value);

-            }

-            return string.Empty;

-        }

-

-        private void GenerateArgumentEnum(CommandLineBuilder builder, BaseProperty property, string value)

-        {

-            var result = ((EnumProperty)property).AdmissibleValues.Find(x => (x.Name == value));

-            if (result != null)

-            {

-                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix, result.Switch);

-            }

-        }

-

-        // helper for string-based properties

-        private void AppendStringValue(CommandLineBuilder builder, BaseProperty property, string subtype, string value)

-        {

-            value = value.Trim();

-

-            // could cache this SubType test off in property wrapper or somewhere if performance were an issue

-            if (subtype == "file" || subtype == "folder")

-            {

-                builder.AppendSwitchIfNotNull(m_parsedBuildRule.SwitchPrefix + property.Switch + property.Separator, value);

-            }

-            else

-            {

-                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix + property.Switch + property.Separator, value);

-            }

-        }

-

-        private void GenerateArgumentStringList(CommandLineBuilder builder, BaseProperty property, string value)

-        {

-			string [] arguments = value.Split(';');

-

-            foreach (string argument in arguments)

-            {

-                if (argument.Length > 0)

-                {

-                    StringListProperty casted = (StringListProperty)property;

-                    AppendStringValue(builder, property, casted.Subtype, argument);

-                }

-            }

-        }

-

-        private void GenerateArgumentString(CommandLineBuilder builder, BaseProperty property, string value)

-        {

-            // could cache this SubType test off in property wrapper or somewhere if performance were an issue

-            StringProperty casted = (StringProperty)property;

-            AppendStringValue(builder, property, casted.Subtype, value);

-        }

-

-        private void GenerateArgumentBool(CommandLineBuilder builder, BaseProperty property, string value)

-        {

-            if (value == "true")

-            {

-                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix, property.Switch);

-            }

-            else if (value == "false" && ((BoolProperty)property).ReverseSwitch != null)

-            {

-                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix, ((BoolProperty)property).ReverseSwitch);

-            }

-        }

-

-        // to store off MSBuild property type and allow faster searching on them

-        private class PropertyWrapper

-        {

-            public PropertyWrapper(Type newType, BaseProperty newProperty)

-            {

-                PropertyType = newType;

-                Property = newProperty;

-            }

-            public Type PropertyType { get; set; }

-            public BaseProperty Property { get; set; }

-        } // class

-

-        private Rule m_parsedBuildRule;

-        private Dictionary<string, PropertyWrapper> ToolProperties { get; set; }

-

-        // function mapping for easy property function calling

-        private Dictionary<Type, Action<CommandLineBuilder, BaseProperty, string>> m_typeFunctionMap;

-    } // XamlParser

-} // namespace NaCl.Build.CPPTasks

-

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Build.Framework;
+using System.Xaml;
+using Microsoft.Build.Framework.XamlTypes;
+using Microsoft.Build.Utilities;
+
+namespace NaCl.Build.CPPTasks
+{
+    class XamlParser
+    {
+        public XamlParser(string path)
+        {
+            // load and store properties from xaml file
+            m_parsedBuildRule = (Rule)XamlServices.Load(path);
+
+            // NOTE: 
+            // There are MSBuild classes which support command line building, 
+            // argument switch encapsulation and more.  Code within VCToolTask, 
+            // a hidden interface, uses some these classes to generate command line 
+            // switches given project settings. As the VCToolTask class is a hidden 
+            // class and the MSBuild documentation is very sparse, we are going 
+            // with a small custom solution.  For reference see the 
+            // Microsoft.Build.Tasks.Xaml, Microsoft.Build.Framework.XamlTypes namespaces.
+
+            // move the properties to a property name keyed dictionary for faster lookup
+            ToolProperties = new Dictionary<string, PropertyWrapper>();
+            ToolProperties = m_parsedBuildRule.Properties.ToDictionary(x => x.Name, x => (new PropertyWrapper(x.GetType(), x)));
+
+            InitFunctionMap();
+        }
+
+        private void InitFunctionMap()
+        {
+            m_typeFunctionMap = new Dictionary<Type, Action<CommandLineBuilder, BaseProperty, string>>
+            {
+                { typeof(StringListProperty), GenerateArgumentStringList },
+                { typeof(StringProperty), GenerateArgumentString },
+                { typeof(IntProperty), GenerateArgumentString },
+                { typeof(BoolProperty), GenerateArgumentBool },
+                { typeof(EnumProperty), GenerateArgumentEnum }
+            };
+        }
+
+        public string Parse(ITaskItem taskItem)
+        {
+            CommandLineBuilder builder = new CommandLineBuilder();
+
+            foreach (string name in taskItem.MetadataNames)
+            {
+                string value = taskItem.GetMetadata(name);
+                AppendArgumentForProperty(builder, name, value);
+            }
+
+            string result = builder.ToString();
+            result = result.Replace('\\', '/'); // posix paths
+            return result;
+        }
+
+        private string AppendArgumentForProperty(CommandLineBuilder builder, string name, string value)
+        {
+            PropertyWrapper current;
+            ToolProperties.TryGetValue(name, out current);
+            if (current != null && value.Length > 0)
+            {
+                // call appropriate function for type
+                m_typeFunctionMap[current.PropertyType](builder, current.Property, value);
+            }
+            return string.Empty;
+        }
+
+        private void GenerateArgumentEnum(CommandLineBuilder builder, BaseProperty property, string value)
+        {
+            var result = ((EnumProperty)property).AdmissibleValues.Find(x => (x.Name == value));
+            if (result != null)
+            {
+                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix, result.Switch);
+            }
+        }
+
+        // helper for string-based properties
+        private void AppendStringValue(CommandLineBuilder builder, BaseProperty property, string subtype, string value)
+        {
+            value = value.Trim();
+
+            // could cache this SubType test off in property wrapper or somewhere if performance were an issue
+            if (subtype == "file" || subtype == "folder")
+            {
+                builder.AppendSwitchIfNotNull(m_parsedBuildRule.SwitchPrefix + property.Switch + property.Separator, value);
+            }
+            else
+            {
+                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix + property.Switch + property.Separator, value);
+            }
+        }
+
+        private void GenerateArgumentStringList(CommandLineBuilder builder, BaseProperty property, string value)
+        {
+			string [] arguments = value.Split(';');
+
+            foreach (string argument in arguments)
+            {
+                if (argument.Length > 0)
+                {
+                    StringListProperty casted = (StringListProperty)property;
+                    AppendStringValue(builder, property, casted.Subtype, argument);
+                }
+            }
+        }
+
+        private void GenerateArgumentString(CommandLineBuilder builder, BaseProperty property, string value)
+        {
+            // could cache this SubType test off in property wrapper or somewhere if performance were an issue
+            StringProperty casted = (StringProperty)property;
+            AppendStringValue(builder, property, casted.Subtype, value);
+        }
+
+        private void GenerateArgumentBool(CommandLineBuilder builder, BaseProperty property, string value)
+        {
+            if (value == "true")
+            {
+                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix, property.Switch);
+            }
+            else if (value == "false" && ((BoolProperty)property).ReverseSwitch != null)
+            {
+                builder.AppendSwitchUnquotedIfNotNull(m_parsedBuildRule.SwitchPrefix, ((BoolProperty)property).ReverseSwitch);
+            }
+        }
+
+        // to store off MSBuild property type and allow faster searching on them
+        private class PropertyWrapper
+        {
+            public PropertyWrapper(Type newType, BaseProperty newProperty)
+            {
+                PropertyType = newType;
+                Property = newProperty;
+            }
+            public Type PropertyType { get; set; }
+            public BaseProperty Property { get; set; }
+        } // class
+
+        private Rule m_parsedBuildRule;
+        private Dictionary<string, PropertyWrapper> ToolProperties { get; set; }
+
+        // function mapping for easy property function calling
+        private Dictionary<Type, Action<CommandLineBuilder, BaseProperty, string>> m_typeFunctionMap;
+    } // XamlParser
+} // namespace NaCl.Build.CPPTasks
+
diff --git a/NativeClientVSAddIn/AssemblyInfo.cs b/NativeClientVSAddIn/AssemblyInfo.cs
index e67e254..76f0d73 100644
--- a/NativeClientVSAddIn/AssemblyInfo.cs
+++ b/NativeClientVSAddIn/AssemblyInfo.cs
@@ -1,31 +1,31 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-using System.Reflection;

-using System.Runtime.CompilerServices;

-

-// General Information about an assembly is controlled through the following

-// set of attributes. Change these attribute values to modify the information

-// associated with an assembly.

-[assembly: AssemblyTitle("Native Client Visual Studio Add-in")]

-[assembly: AssemblyDescription("An add-in for Visual Studio aiding Native Client development")]

-[assembly: AssemblyConfiguration("")]

-[assembly: AssemblyCompany("Google Inc.")]

-[assembly: AssemblyProduct("Native Client SDK Visual Studio Add-in")]

-[assembly: AssemblyCopyright("Copyright © 2012 The Chromium Authors")]

-[assembly: AssemblyTrademark("")]

-[assembly: AssemblyCulture("")]

-

-// Version information for an assembly consists of the following four values:

-//

-//    Major Version

-//    Minor Version

-//    Revision

-//    Build Number

-//

-// You can specify all the value or you can default the Revision and

-// Build Numbers by using the '*' as shown below:

-[assembly: AssemblyVersion("1.0.*")]

-

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Native Client Visual Studio Add-in")]
+[assembly: AssemblyDescription("An add-in for Visual Studio aiding Native Client development")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Google Inc.")]
+[assembly: AssemblyProduct("Native Client SDK Visual Studio Add-in")]
+[assembly: AssemblyCopyright("Copyright © 2012 The Chromium Authors")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+//    Major Version
+//    Minor Version
+//    Revision
+//    Build Number
+//
+// You can specify all the value or you can default the Revision and
+// Build Numbers by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.*")]
+
 [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("UnitTests")]
\ No newline at end of file
diff --git a/NativeClientVSAddIn/PluginDebuggerBase.cs b/NativeClientVSAddIn/PluginDebuggerBase.cs
index 0d0e64b..71c23a0 100644
--- a/NativeClientVSAddIn/PluginDebuggerBase.cs
+++ b/NativeClientVSAddIn/PluginDebuggerBase.cs
@@ -1,239 +1,239 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace NativeClientVSAddIn

-{

-  using System;

-  using System.Collections.Generic;

-  using System.Windows.Forms;

-

-  using EnvDTE;

-  using EnvDTE80;

-

-  /// <summary>

-  /// This is a base class for encapsulating functionality related to attaching a debugger

-  /// to a nacl/pepper plug-in.  This base class mostly contains functionality related to finding

-  /// the plug-in.

-  /// </summary>

-  public class PluginDebuggerBase : IDisposable

-  {

-    /// <summary>

-    /// This is the initial number of milliseconds to wait between

-    /// checking for plug-in processes to attach the debugger to.

-    /// </summary>

-    private const int InitialPluginCheckFrequency = 1000;

-

-    /// <summary>

-    /// After a plug-in has been found, we slow the frequency of checking

-    /// for new ones. This value is in milliseconds.

-    /// </summary>

-    private const int RelaxedPluginCheckFrequency = 5000;

-

-    /// <summary>

-    /// Timer object that periodically calls a function to look for the plug-in process to debug.

-    /// </summary>

-    private Timer pluginFinderTimer_;

-

-    /// <summary>

-    /// List of process IDs which we should not attempt to attach the debugger to. Mainly this

-    /// list contains process IDs of processes we have already attached to.

-    /// </summary>

-    private List<uint> pluginFinderForbiddenPids_;

-

-    /// <summary>

-    /// Process searcher class which allows us to query the system for running processes.

-    /// </summary>

-    private ProcessSearcher processSearcher_;

-

-    /// <summary>

-    /// The main process of chrome that was started by Visual Studio during debugging.

-    /// </summary>

-    private System.Diagnostics.Process debuggedChromeMainProcess_;

-

-    /// <summary>

-    /// Constructs the PluginDebuggerHelper.

-    /// </summary>

-    /// <param name="dte">Automation object from Visual Studio.</param>

-    /// <param name="properties">PropertyManager set to a valid project/platform.</param>

-    protected PluginDebuggerBase(DTE2 dte, PropertyManager properties)

-    {

-      if (dte == null)

-      {

-        throw new ArgumentNullException("dte");

-      }

-

-      if (properties == null)

-      {

-        throw new ArgumentNullException("properties");

-      }

-

-      Dte = dte;

-

-      // Every second, check for a new instance of the plug-in to attach to.

-      // Note that although the timer itself runs on a separate thread, the event

-      // is fired from the main UI thread during message processing, thus we do not

-      // need to worry about threading issues.

-      pluginFinderTimer_ = new Timer();

-      pluginFinderTimer_.Tick += new EventHandler(FindAndAttachToPlugin);

-      pluginFinderForbiddenPids_ = new List<uint>();

-      processSearcher_ = new ProcessSearcher();

-

-      pluginFinderTimer_.Interval = InitialPluginCheckFrequency;

-      pluginFinderTimer_.Start();

-    }

-

-    /// <summary>

-    /// Finalizer. Should clean up unmanaged resources. Should not be overriden in derived classes.

-    /// </summary>

-    ~PluginDebuggerBase()

-    {

-      Dispose(false);

-    }

-

-    /// <summary>

-    /// An event indicating a target plug-in was found on the system.

-    /// </summary>

-    public event EventHandler<PluginFoundEventArgs> PluginFoundEvent;

-

-    /// <summary>

-    /// Gets or sets a value indicating whether this object has been disposed of already.

-    /// </summary>

-    protected bool Disposed { get; set; }

-

-    /// <summary>

-    /// Gets or sets the main visual studio object.

-    /// </summary>

-    protected DTE2 Dte { get; set; }

-

-    /// <summary>

-    /// Disposes the object when called by user code (not directly by garbage collector).

-    /// </summary>

-    public void Dispose()

-    {

-      Dispose(true);

-      GC.SuppressFinalize(this);

-    }

-

-    /// <summary>

-    /// This is called periodically by the Visual Studio UI thread to look for our plug-in process

-    /// and attach the debugger to it.  The call is triggered by the pluginFinderTimer_ object.

-    /// </summary>

-    /// <param name="unused">The parameter is not used.</param>

-    /// <param name="unused1">The parameter is not used.</param>

-    public void FindAndAttachToPlugin(object unused, EventArgs unused1)

-    {

-      StringComparison ignoreCase = StringComparison.InvariantCultureIgnoreCase;

-

-      // This function is called by the main Visual Studio event loop and we may have put the event

-      // on the queue just before disposing it meaning this could be called after we've disposed.

-      if (Disposed)

-      {

-        return;

-      }

-

-      // Set the main chrome process that was started by visual studio.  If it's not chrome

-      // or not found then we have no business attaching to any plug-ins so return.

-      if (debuggedChromeMainProcess_ == null)

-      {

-        foreach (Process proc in Dte.Debugger.DebuggedProcesses)

-        {

-          if (proc.Name.EndsWith(Strings.ChromeProcessName, ignoreCase))

-          {

-            debuggedChromeMainProcess_ = System.Diagnostics.Process.GetProcessById(proc.ProcessID);

-            break;

-          }

-        }

-

-        return;

-      }

-

-      if (debuggedChromeMainProcess_.HasExited)

-      {

-        // Might happen if we're shutting down debugging.

-        return;

-      }

-

-      // Get the list of all descendants of the main chrome process.

-      uint mainChromeProcId = (uint)debuggedChromeMainProcess_.Id;

-      List<ProcessInfo> chromeDescendants = processSearcher_.GetDescendants(mainChromeProcId);

-      if (chromeDescendants.Count == 0)

-      {

-        // Might happen if we're shutting down debugging.

-        return;

-      }

-

-      ProcessInfo mainProcInfo = chromeDescendants.Find(p => p.ID == mainChromeProcId);

-      if (mainProcInfo == null)

-      {

-        // Might happen if we're shutting down debugging.

-        return;

-      }

-

-      string mainChromeFlags = mainProcInfo.CommandLine;

-

-      // From the list of descendants, find the plug-in by it's command line arguments and

-      // process name as well as not being attached to already.

-      List<ProcessInfo> plugins = chromeDescendants.FindAll(p =>

-          IsPluginProcess(p, mainChromeFlags) && !pluginFinderForbiddenPids_.Contains(p.ID));

-

-      // Attach to all plug-ins that we found.

-      foreach (ProcessInfo process in plugins)

-      {

-        // If we are attaching to a plug-in, add it to the forbidden list to ensure we

-        // don't try to attach again later.

-        pluginFinderForbiddenPids_.Add(process.ID);

-        PluginFoundEvent.Invoke(this, new PluginFoundEventArgs(process.ID));

-

-        // Slow down the frequency of checks for new plugins.

-        pluginFinderTimer_.Interval = RelaxedPluginCheckFrequency;

-      }

-    }

-

-    /// <summary>

-    /// Disposes the object. If disposing is false then this has been called by garbage collection,

-    /// and we shouldn't reference managed objects.

-    /// </summary>

-    /// <param name="disposing">True if user call to Dispose, false if garbase collection.</param>

-    protected virtual void Dispose(bool disposing)

-    {

-      if (!Disposed && disposing)

-      {

-        pluginFinderTimer_.Stop();

-      }

-      

-      Disposed = true;

-    }

-

-    /// <summary>

-    /// Called to check if a process is a valid plugin to attach to.

-    /// </summary>

-    /// <param name="proc">Contains information about the process in question.</param>

-    /// <param name="mainChromeFlags">Flags on the main Chrome process.</param>

-    /// <returns>True if we should attach to the process.</returns>

-    protected virtual bool IsPluginProcess(ProcessInfo proc, string mainChromeFlags)

-    {

-      throw new InvalidOperationException();

-    }

-

-    /// <summary>

-    /// The event arguments when a plug-in is found.

-    /// </summary>

-    public class PluginFoundEventArgs : EventArgs

-    {

-      /// <summary>

-      /// Construct the PluginFoundEventArgs.

-      /// </summary>

-      /// <param name="pid">Process ID of the found plug-in.</param>

-      public PluginFoundEventArgs(uint pid)

-      {

-        this.ProcessID = pid;

-      }

-

-      /// <summary>

-      /// Gets or sets process ID of the found plug-in.

-      /// </summary>

-      public uint ProcessID { get; set; }

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace NativeClientVSAddIn
+{
+  using System;
+  using System.Collections.Generic;
+  using System.Windows.Forms;
+
+  using EnvDTE;
+  using EnvDTE80;
+
+  /// <summary>
+  /// This is a base class for encapsulating functionality related to attaching a debugger
+  /// to a nacl/pepper plug-in.  This base class mostly contains functionality related to finding
+  /// the plug-in.
+  /// </summary>
+  public class PluginDebuggerBase : IDisposable
+  {
+    /// <summary>
+    /// This is the initial number of milliseconds to wait between
+    /// checking for plug-in processes to attach the debugger to.
+    /// </summary>
+    private const int InitialPluginCheckFrequency = 1000;
+
+    /// <summary>
+    /// After a plug-in has been found, we slow the frequency of checking
+    /// for new ones. This value is in milliseconds.
+    /// </summary>
+    private const int RelaxedPluginCheckFrequency = 5000;
+
+    /// <summary>
+    /// Timer object that periodically calls a function to look for the plug-in process to debug.
+    /// </summary>
+    private Timer pluginFinderTimer_;
+
+    /// <summary>
+    /// List of process IDs which we should not attempt to attach the debugger to. Mainly this
+    /// list contains process IDs of processes we have already attached to.
+    /// </summary>
+    private List<uint> pluginFinderForbiddenPids_;
+
+    /// <summary>
+    /// Process searcher class which allows us to query the system for running processes.
+    /// </summary>
+    private ProcessSearcher processSearcher_;
+
+    /// <summary>
+    /// The main process of chrome that was started by Visual Studio during debugging.
+    /// </summary>
+    private System.Diagnostics.Process debuggedChromeMainProcess_;
+
+    /// <summary>
+    /// Constructs the PluginDebuggerHelper.
+    /// </summary>
+    /// <param name="dte">Automation object from Visual Studio.</param>
+    /// <param name="properties">PropertyManager set to a valid project/platform.</param>
+    protected PluginDebuggerBase(DTE2 dte, PropertyManager properties)
+    {
+      if (dte == null)
+      {
+        throw new ArgumentNullException("dte");
+      }
+
+      if (properties == null)
+      {
+        throw new ArgumentNullException("properties");
+      }
+
+      Dte = dte;
+
+      // Every second, check for a new instance of the plug-in to attach to.
+      // Note that although the timer itself runs on a separate thread, the event
+      // is fired from the main UI thread during message processing, thus we do not
+      // need to worry about threading issues.
+      pluginFinderTimer_ = new Timer();
+      pluginFinderTimer_.Tick += new EventHandler(FindAndAttachToPlugin);
+      pluginFinderForbiddenPids_ = new List<uint>();
+      processSearcher_ = new ProcessSearcher();
+
+      pluginFinderTimer_.Interval = InitialPluginCheckFrequency;
+      pluginFinderTimer_.Start();
+    }
+
+    /// <summary>
+    /// Finalizer. Should clean up unmanaged resources. Should not be overriden in derived classes.
+    /// </summary>
+    ~PluginDebuggerBase()
+    {
+      Dispose(false);
+    }
+
+    /// <summary>
+    /// An event indicating a target plug-in was found on the system.
+    /// </summary>
+    public event EventHandler<PluginFoundEventArgs> PluginFoundEvent;
+
+    /// <summary>
+    /// Gets or sets a value indicating whether this object has been disposed of already.
+    /// </summary>
+    protected bool Disposed { get; set; }
+
+    /// <summary>
+    /// Gets or sets the main visual studio object.
+    /// </summary>
+    protected DTE2 Dte { get; set; }
+
+    /// <summary>
+    /// Disposes the object when called by user code (not directly by garbage collector).
+    /// </summary>
+    public void Dispose()
+    {
+      Dispose(true);
+      GC.SuppressFinalize(this);
+    }
+
+    /// <summary>
+    /// This is called periodically by the Visual Studio UI thread to look for our plug-in process
+    /// and attach the debugger to it.  The call is triggered by the pluginFinderTimer_ object.
+    /// </summary>
+    /// <param name="unused">The parameter is not used.</param>
+    /// <param name="unused1">The parameter is not used.</param>
+    public void FindAndAttachToPlugin(object unused, EventArgs unused1)
+    {
+      StringComparison ignoreCase = StringComparison.InvariantCultureIgnoreCase;
+
+      // This function is called by the main Visual Studio event loop and we may have put the event
+      // on the queue just before disposing it meaning this could be called after we've disposed.
+      if (Disposed)
+      {
+        return;
+      }
+
+      // Set the main chrome process that was started by visual studio.  If it's not chrome
+      // or not found then we have no business attaching to any plug-ins so return.
+      if (debuggedChromeMainProcess_ == null)
+      {
+        foreach (Process proc in Dte.Debugger.DebuggedProcesses)
+        {
+          if (proc.Name.EndsWith(Strings.ChromeProcessName, ignoreCase))
+          {
+            debuggedChromeMainProcess_ = System.Diagnostics.Process.GetProcessById(proc.ProcessID);
+            break;
+          }
+        }
+
+        return;
+      }
+
+      if (debuggedChromeMainProcess_.HasExited)
+      {
+        // Might happen if we're shutting down debugging.
+        return;
+      }
+
+      // Get the list of all descendants of the main chrome process.
+      uint mainChromeProcId = (uint)debuggedChromeMainProcess_.Id;
+      List<ProcessInfo> chromeDescendants = processSearcher_.GetDescendants(mainChromeProcId);
+      if (chromeDescendants.Count == 0)
+      {
+        // Might happen if we're shutting down debugging.
+        return;
+      }
+
+      ProcessInfo mainProcInfo = chromeDescendants.Find(p => p.ID == mainChromeProcId);
+      if (mainProcInfo == null)
+      {
+        // Might happen if we're shutting down debugging.
+        return;
+      }
+
+      string mainChromeFlags = mainProcInfo.CommandLine;
+
+      // From the list of descendants, find the plug-in by it's command line arguments and
+      // process name as well as not being attached to already.
+      List<ProcessInfo> plugins = chromeDescendants.FindAll(p =>
+          IsPluginProcess(p, mainChromeFlags) && !pluginFinderForbiddenPids_.Contains(p.ID));
+
+      // Attach to all plug-ins that we found.
+      foreach (ProcessInfo process in plugins)
+      {
+        // If we are attaching to a plug-in, add it to the forbidden list to ensure we
+        // don't try to attach again later.
+        pluginFinderForbiddenPids_.Add(process.ID);
+        PluginFoundEvent.Invoke(this, new PluginFoundEventArgs(process.ID));
+
+        // Slow down the frequency of checks for new plugins.
+        pluginFinderTimer_.Interval = RelaxedPluginCheckFrequency;
+      }
+    }
+
+    /// <summary>
+    /// Disposes the object. If disposing is false then this has been called by garbage collection,
+    /// and we shouldn't reference managed objects.
+    /// </summary>
+    /// <param name="disposing">True if user call to Dispose, false if garbase collection.</param>
+    protected virtual void Dispose(bool disposing)
+    {
+      if (!Disposed && disposing)
+      {
+        pluginFinderTimer_.Stop();
+      }
+      
+      Disposed = true;
+    }
+
+    /// <summary>
+    /// Called to check if a process is a valid plugin to attach to.
+    /// </summary>
+    /// <param name="proc">Contains information about the process in question.</param>
+    /// <param name="mainChromeFlags">Flags on the main Chrome process.</param>
+    /// <returns>True if we should attach to the process.</returns>
+    protected virtual bool IsPluginProcess(ProcessInfo proc, string mainChromeFlags)
+    {
+      throw new InvalidOperationException();
+    }
+
+    /// <summary>
+    /// The event arguments when a plug-in is found.
+    /// </summary>
+    public class PluginFoundEventArgs : EventArgs
+    {
+      /// <summary>
+      /// Construct the PluginFoundEventArgs.
+      /// </summary>
+      /// <param name="pid">Process ID of the found plug-in.</param>
+      public PluginFoundEventArgs(uint pid)
+      {
+        this.ProcessID = pid;
+      }
+
+      /// <summary>
+      /// Gets or sets process ID of the found plug-in.
+      /// </summary>
+      public uint ProcessID { get; set; }
+    }
+  }
+}
diff --git a/NativeClientVSAddIn/PluginDebuggerVS.cs b/NativeClientVSAddIn/PluginDebuggerVS.cs
index 2ad73e8..be2feb5 100644
--- a/NativeClientVSAddIn/PluginDebuggerVS.cs
+++ b/NativeClientVSAddIn/PluginDebuggerVS.cs
@@ -1,66 +1,66 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace NativeClientVSAddIn

-{

-  using System;

-

-  using EnvDTE80;

-

-  /// <summary>

-  /// This class handles the details of finding a pepper plugin and attaching to it.

-  /// </summary>

-  public class PluginDebuggerVS : PluginDebuggerBase

-  {

-    /// <summary>

-    /// Path to the actual plug-in assembly.

-    /// </summary>

-    private string pluginAssembly_;

-

-    /// <summary>

-    /// Constructs the PluginDebuggerHelper.

-    /// </summary>

-    /// <param name="dte">Automation object from Visual Studio.</param>

-    /// <param name="properties">PropertyManager pointing to a valid project/platform.</param>

-    public PluginDebuggerVS(DTE2 dte, PropertyManager properties)

-        : base(dte, properties)

-    {

-      pluginAssembly_ = properties.PluginAssembly;

-      PluginFoundEvent += new EventHandler<PluginFoundEventArgs>(Attach);

-    }

-

-    /// <summary>

-    /// Called to check if a process is a valid pepper plugin to attach to.

-    /// </summary>

-    /// <param name="proc">Contains information about the process in question.</param>

-    /// <param name="mainChromeFlags">Flags on the main Chrome process.</param>

-    /// <returns>True if we should attach to the process.</returns>

-    protected override bool IsPluginProcess(ProcessInfo proc, string mainChromeFlags)

-    {

-      StringComparison ignoreCase = StringComparison.InvariantCultureIgnoreCase;

-      string identifierFlagTarget =

-              string.Format(Strings.PepperProcessPluginFlagFormat, pluginAssembly_);

-      return proc.Name.Equals(Strings.ChromeProcessName, ignoreCase) &&

-             proc.CommandLine.Contains(Strings.ChromeRendererFlag, ignoreCase) &&

-             proc.CommandLine.Contains(identifierFlagTarget, ignoreCase);

-    }

-

-    /// <summary>

-    /// Attaches the Visual Studio debugger to the given process ID.

-    /// </summary>

-    /// <param name="src">The parameter is not used.</param>

-    /// <param name="args">Contains the process ID to attach to.</param>

-    private void Attach(object src, PluginFoundEventArgs args)

-    {

-      foreach (EnvDTE.Process proc in Dte.Debugger.LocalProcesses)

-      {

-        if (proc.ProcessID == args.ProcessID)

-        {

-          proc.Attach();

-          break;

-        }

-      }

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace NativeClientVSAddIn
+{
+  using System;
+
+  using EnvDTE80;
+
+  /// <summary>
+  /// This class handles the details of finding a pepper plugin and attaching to it.
+  /// </summary>
+  public class PluginDebuggerVS : PluginDebuggerBase
+  {
+    /// <summary>
+    /// Path to the actual plug-in assembly.
+    /// </summary>
+    private string pluginAssembly_;
+
+    /// <summary>
+    /// Constructs the PluginDebuggerHelper.
+    /// </summary>
+    /// <param name="dte">Automation object from Visual Studio.</param>
+    /// <param name="properties">PropertyManager pointing to a valid project/platform.</param>
+    public PluginDebuggerVS(DTE2 dte, PropertyManager properties)
+        : base(dte, properties)
+    {
+      pluginAssembly_ = properties.PluginAssembly;
+      PluginFoundEvent += new EventHandler<PluginFoundEventArgs>(Attach);
+    }
+
+    /// <summary>
+    /// Called to check if a process is a valid pepper plugin to attach to.
+    /// </summary>
+    /// <param name="proc">Contains information about the process in question.</param>
+    /// <param name="mainChromeFlags">Flags on the main Chrome process.</param>
+    /// <returns>True if we should attach to the process.</returns>
+    protected override bool IsPluginProcess(ProcessInfo proc, string mainChromeFlags)
+    {
+      StringComparison ignoreCase = StringComparison.InvariantCultureIgnoreCase;
+      string identifierFlagTarget =
+              string.Format(Strings.PepperProcessPluginFlagFormat, pluginAssembly_);
+      return proc.Name.Equals(Strings.ChromeProcessName, ignoreCase) &&
+             proc.CommandLine.Contains(Strings.ChromeRendererFlag, ignoreCase) &&
+             proc.CommandLine.Contains(identifierFlagTarget, ignoreCase);
+    }
+
+    /// <summary>
+    /// Attaches the Visual Studio debugger to the given process ID.
+    /// </summary>
+    /// <param name="src">The parameter is not used.</param>
+    /// <param name="args">Contains the process ID to attach to.</param>
+    private void Attach(object src, PluginFoundEventArgs args)
+    {
+      foreach (EnvDTE.Process proc in Dte.Debugger.LocalProcesses)
+      {
+        if (proc.ProcessID == args.ProcessID)
+        {
+          proc.Attach();
+          break;
+        }
+      }
+    }
+  }
+}
diff --git a/NativeClientVSAddIn/ProcessInfo.cs b/NativeClientVSAddIn/ProcessInfo.cs
index 118b5b4..ca5333a 100644
--- a/NativeClientVSAddIn/ProcessInfo.cs
+++ b/NativeClientVSAddIn/ProcessInfo.cs
@@ -1,90 +1,90 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace NativeClientVSAddIn

-{

-  using System;

-  using System.Globalization;

-  using System.Management;

-

-  /// <summary>

-  /// Holds information about a process for a ProcessSearcher.

-  /// </summary>

-  public class ProcessInfo

-  {

-    /// <summary>

-    /// Constructs a process entry.

-    /// </summary>

-    /// <param name="id">Process ID.</param>

-    /// <param name="parentId">Process ID of the parent process.</param>

-    /// <param name="creationDate">

-    /// String date in format 'yyyyMMddHHmmss.ffffff', or if empty then current time used.

-    /// </param>

-    /// <param name="commandLine">Command line arguments to the process.</param>

-    /// <param name="name">Process name.</param>

-    public ProcessInfo(uint id, uint parentId, string creationDate, string commandLine, string name)

-    {

-      if (string.IsNullOrEmpty(creationDate))

-      {

-        // If creationDate string is empty, then use the current timestamp.

-        CreationDate = DateTime.UtcNow;

-      }

-      else

-      {

-        // Example creationDate: "20120622150149.843021-420".

-        CreationDate = DateTime.ParseExact(

-            creationDate.Substring(0, 21),

-            "yyyyMMddHHmmss.ffffff",

-            CultureInfo.InvariantCulture);

-        long timeZoneMinutes = long.Parse(creationDate.Substring(21));

-        CreationDate = CreationDate.AddMinutes(-timeZoneMinutes);

-      }

-

-      ID = id;

-      ParentID = parentId;

-      CommandLine = commandLine;

-      Name = name;

-    }

-

-    /// <summary>

-    /// Gets or sets Process ID of the represented process.

-    /// </summary>

-    public uint ID { get; set; }

-

-    /// <summary>

-    /// Gets or sets Process ID of the parent process.

-    /// </summary>

-    public uint ParentID { get; set; }

-

-    /// <summary>

-    /// Gets or sets DateTime of the process creation.

-    /// </summary>

-    public DateTime CreationDate { get; set; }

-

-    /// <summary>

-    /// Gets or sets Command line arguments to the process.

-    /// </summary>

-    public string CommandLine { get; set; }

-

-    /// <summary>

-    /// Gets or sets Name of the process.

-    /// </summary>

-    public string Name { get; set; }

-

-    /// <summary>

-    /// Casts from a management object that is a Win32_Process underlying type to a ProcessInfo.

-    /// </summary>

-    /// <param name="from">A management object that is Win32_Process underneath.</param>

-    /// <returns>A ProcessInfo object.</returns>

-    public static explicit operator ProcessInfo(ManagementObject from)

-    {

-      return new ProcessInfo(

-          id: (uint)from["ProcessID"],

-          parentId: (uint)from["ParentProcessID"],

-          creationDate: from["CreationDate"] as string,

-          commandLine: from["CommandLine"] as string,

-          name: from["Name"] as string);

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace NativeClientVSAddIn
+{
+  using System;
+  using System.Globalization;
+  using System.Management;
+
+  /// <summary>
+  /// Holds information about a process for a ProcessSearcher.
+  /// </summary>
+  public class ProcessInfo
+  {
+    /// <summary>
+    /// Constructs a process entry.
+    /// </summary>
+    /// <param name="id">Process ID.</param>
+    /// <param name="parentId">Process ID of the parent process.</param>
+    /// <param name="creationDate">
+    /// String date in format 'yyyyMMddHHmmss.ffffff', or if empty then current time used.
+    /// </param>
+    /// <param name="commandLine">Command line arguments to the process.</param>
+    /// <param name="name">Process name.</param>
+    public ProcessInfo(uint id, uint parentId, string creationDate, string commandLine, string name)
+    {
+      if (string.IsNullOrEmpty(creationDate))
+      {
+        // If creationDate string is empty, then use the current timestamp.
+        CreationDate = DateTime.UtcNow;
+      }
+      else
+      {
+        // Example creationDate: "20120622150149.843021-420".
+        CreationDate = DateTime.ParseExact(
+            creationDate.Substring(0, 21),
+            "yyyyMMddHHmmss.ffffff",
+            CultureInfo.InvariantCulture);
+        long timeZoneMinutes = long.Parse(creationDate.Substring(21));
+        CreationDate = CreationDate.AddMinutes(-timeZoneMinutes);
+      }
+
+      ID = id;
+      ParentID = parentId;
+      CommandLine = commandLine;
+      Name = name;
+    }
+
+    /// <summary>
+    /// Gets or sets Process ID of the represented process.
+    /// </summary>
+    public uint ID { get; set; }
+
+    /// <summary>
+    /// Gets or sets Process ID of the parent process.
+    /// </summary>
+    public uint ParentID { get; set; }
+
+    /// <summary>
+    /// Gets or sets DateTime of the process creation.
+    /// </summary>
+    public DateTime CreationDate { get; set; }
+
+    /// <summary>
+    /// Gets or sets Command line arguments to the process.
+    /// </summary>
+    public string CommandLine { get; set; }
+
+    /// <summary>
+    /// Gets or sets Name of the process.
+    /// </summary>
+    public string Name { get; set; }
+
+    /// <summary>
+    /// Casts from a management object that is a Win32_Process underlying type to a ProcessInfo.
+    /// </summary>
+    /// <param name="from">A management object that is Win32_Process underneath.</param>
+    /// <returns>A ProcessInfo object.</returns>
+    public static explicit operator ProcessInfo(ManagementObject from)
+    {
+      return new ProcessInfo(
+          id: (uint)from["ProcessID"],
+          parentId: (uint)from["ParentProcessID"],
+          creationDate: from["CreationDate"] as string,
+          commandLine: from["CommandLine"] as string,
+          name: from["Name"] as string);
+    }
+  }
+}
diff --git a/NativeClientVSAddIn/ProcessSearcher.cs b/NativeClientVSAddIn/ProcessSearcher.cs
index ceb3b0d..3657553 100644
--- a/NativeClientVSAddIn/ProcessSearcher.cs
+++ b/NativeClientVSAddIn/ProcessSearcher.cs
@@ -1,96 +1,96 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace NativeClientVSAddIn

-{

-  using System;

-  using System.Collections.Generic;

-  using System.Linq;

-  using System.Management;

-

-  /// <summary>

-  /// Queries the system for the list of running processes.

-  /// </summary>

-  public class ProcessSearcher

-  {

-    /// <summary>

-    /// Returns results of a process search subject to given constraints.

-    /// </summary>

-    /// <param name="constraints">

-    /// A function taking a ProcessInfo object and returning true if the

-    /// ProcessInfo object satisfies the constraints.

-    /// </param>

-    /// <returns>List of matching processes.</returns>

-    public List<ProcessInfo> GetResults(Func<ProcessInfo, bool> constraints)

-    {

-      return GetSystemProcesses().Where(constraints).ToList();

-    }

-

-    /// <summary>

-    /// Searches the system for all processes of a given name.

-    /// </summary>

-    /// <param name="name">Name to search for.</param>

-    /// <returns>List of matching processes.</returns>

-    public List<ProcessInfo> GetResultsByName(string name)

-    {

-      return GetResults(p => name.Equals(p.Name, StringComparison.OrdinalIgnoreCase));

-    }

-

-    /// <summary>

-    /// Searches the system for all processes of a given process ID.

-    /// </summary>

-    /// <param name="procID">ID to search for.</param>

-    /// <returns>List of matching processes.</returns>

-    public List<ProcessInfo> GetResultsByID(uint procID)

-    {

-      return GetResults(p => procID == p.ID);

-    }

-

-    /// <summary>

-    /// Returns a list of all descendant processes of a process.

-    /// </summary>

-    /// <param name="root">Process ID of the process to get all descendants from.</param>

-    /// <returns>All descendants of the given root process.</returns>

-    public List<ProcessInfo> GetDescendants(uint root)

-    {

-      List<ProcessInfo> processes = GetSystemProcesses();

-      HashSet<ProcessInfo> descendants = new HashSet<ProcessInfo>();

-      descendants.UnionWith(processes.Where(p => p.ID == root));

-      int lastCount = 0;

-      while (descendants.Count > lastCount)

-      {

-        lastCount = descendants.Count;

-

-        // Add any processes who have a parent that is in the descendant list already.

-        // Note we check the creation date to prevent cycles caused by recycled process IDs.

-        descendants.UnionWith(processes.Where(p => descendants.Any(

-            parent => parent.ID == p.ParentID && parent.CreationDate <= p.CreationDate)));

-      }

-

-      return descendants.ToList();

-    }

-

-    /// <summary>

-    /// Queries the system for the full list of processes.

-    /// </summary>

-    /// <returns>List of processes on the system.</returns>

-    protected virtual List<ProcessInfo> GetSystemProcesses()

-    {

-      var processList = new List<ProcessInfo>();

-      string query = "select * from Win32_Process";

-      using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))

-      {

-        using (ManagementObjectCollection results = searcher.Get())

-        {

-          foreach (ManagementObject process in results)

-          {

-            processList.Add((ProcessInfo)process);

-          }

-        }

-      }

-

-      return processList;

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace NativeClientVSAddIn
+{
+  using System;
+  using System.Collections.Generic;
+  using System.Linq;
+  using System.Management;
+
+  /// <summary>
+  /// Queries the system for the list of running processes.
+  /// </summary>
+  public class ProcessSearcher
+  {
+    /// <summary>
+    /// Returns results of a process search subject to given constraints.
+    /// </summary>
+    /// <param name="constraints">
+    /// A function taking a ProcessInfo object and returning true if the
+    /// ProcessInfo object satisfies the constraints.
+    /// </param>
+    /// <returns>List of matching processes.</returns>
+    public List<ProcessInfo> GetResults(Func<ProcessInfo, bool> constraints)
+    {
+      return GetSystemProcesses().Where(constraints).ToList();
+    }
+
+    /// <summary>
+    /// Searches the system for all processes of a given name.
+    /// </summary>
+    /// <param name="name">Name to search for.</param>
+    /// <returns>List of matching processes.</returns>
+    public List<ProcessInfo> GetResultsByName(string name)
+    {
+      return GetResults(p => name.Equals(p.Name, StringComparison.OrdinalIgnoreCase));
+    }
+
+    /// <summary>
+    /// Searches the system for all processes of a given process ID.
+    /// </summary>
+    /// <param name="procID">ID to search for.</param>
+    /// <returns>List of matching processes.</returns>
+    public List<ProcessInfo> GetResultsByID(uint procID)
+    {
+      return GetResults(p => procID == p.ID);
+    }
+
+    /// <summary>
+    /// Returns a list of all descendant processes of a process.
+    /// </summary>
+    /// <param name="root">Process ID of the process to get all descendants from.</param>
+    /// <returns>All descendants of the given root process.</returns>
+    public List<ProcessInfo> GetDescendants(uint root)
+    {
+      List<ProcessInfo> processes = GetSystemProcesses();
+      HashSet<ProcessInfo> descendants = new HashSet<ProcessInfo>();
+      descendants.UnionWith(processes.Where(p => p.ID == root));
+      int lastCount = 0;
+      while (descendants.Count > lastCount)
+      {
+        lastCount = descendants.Count;
+
+        // Add any processes who have a parent that is in the descendant list already.
+        // Note we check the creation date to prevent cycles caused by recycled process IDs.
+        descendants.UnionWith(processes.Where(p => descendants.Any(
+            parent => parent.ID == p.ParentID && parent.CreationDate <= p.CreationDate)));
+      }
+
+      return descendants.ToList();
+    }
+
+    /// <summary>
+    /// Queries the system for the full list of processes.
+    /// </summary>
+    /// <returns>List of processes on the system.</returns>
+    protected virtual List<ProcessInfo> GetSystemProcesses()
+    {
+      var processList = new List<ProcessInfo>();
+      string query = "select * from Win32_Process";
+      using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
+      {
+        using (ManagementObjectCollection results = searcher.Get())
+        {
+          foreach (ManagementObject process in results)
+          {
+            processList.Add((ProcessInfo)process);
+          }
+        }
+      }
+
+      return processList;
+    }
+  }
+}
diff --git a/NativeClientVSAddIn/Strings.Designer.cs b/NativeClientVSAddIn/Strings.Designer.cs
index f6ba255..26f5a52 100644
--- a/NativeClientVSAddIn/Strings.Designer.cs
+++ b/NativeClientVSAddIn/Strings.Designer.cs
@@ -1,234 +1,234 @@
-//------------------------------------------------------------------------------

-// <auto-generated>

-//     This code was generated by a tool.

-//     Runtime Version:4.0.30319.269

-//

-//     Changes to this file may cause incorrect behavior and will be lost if

-//     the code is regenerated.

-// </auto-generated>

-//------------------------------------------------------------------------------

-

-namespace NativeClientVSAddIn {

-    using System;

-    

-    

-    /// <summary>

-    ///   A strongly-typed resource class, for looking up localized strings, etc.

-    /// </summary>

-    // This class was auto-generated by the StronglyTypedResourceBuilder

-    // class via a tool like ResGen or Visual Studio.

-    // To add or remove a member, edit your .ResX file then rerun ResGen

-    // with the /str option, or rebuild your VS project.

-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]

-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

-    internal class Strings {

-        

-        private static global::System.Resources.ResourceManager resourceMan;

-        

-        private static global::System.Globalization.CultureInfo resourceCulture;

-        

-        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]

-        internal Strings() {

-        }

-        

-        /// <summary>

-        ///   Returns the cached ResourceManager instance used by this class.

-        /// </summary>

-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

-        internal static global::System.Resources.ResourceManager ResourceManager {

-            get {

-                if (object.ReferenceEquals(resourceMan, null)) {

-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NativeClientVSAddIn.Strings", typeof(Strings).Assembly);

-                    resourceMan = temp;

-                }

-                return resourceMan;

-            }

-        }

-        

-        /// <summary>

-        ///   Overrides the current thread's CurrentUICulture property for all

-        ///   resource lookups using this strongly typed resource class.

-        /// </summary>

-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]

-        internal static global::System.Globalization.CultureInfo Culture {

-            get {

-                return resourceCulture;

-            }

-            set {

-                resourceCulture = value;

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Native Client Visual Studio Add-In.

-        /// </summary>

-        internal static string AddInName {

-            get {

-                return ResourceManager.GetString("AddInName", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to CHROME_PATH.

-        /// </summary>

-        internal static string ChromePathEnvironmentVariable {

-            get {

-                return ResourceManager.GetString("ChromePathEnvironmentVariable", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to chrome.exe.

-        /// </summary>

-        internal static string ChromeProcessName {

-            get {

-                return ResourceManager.GetString("ChromeProcessName", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to --type=renderer.

-        /// </summary>

-        internal static string ChromeRendererFlag {

-            get {

-                return ResourceManager.GetString("ChromeRendererFlag", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Warning: Multiple start-up projects not supported. Web server will only be run from first project directory.

-        /// </summary>

-        internal static string MultiStartProjectWarning {

-            get {

-                return ResourceManager.GetString("MultiStartProjectWarning", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to --enable-nacl-debug.

-        /// </summary>

-        internal static string NaClDebugFlag {

-            get {

-                return ResourceManager.GetString("NaClDebugFlag", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to --type=nacl-loader.

-        /// </summary>

-        internal static string NaClLoaderFlag {

-            get {

-                return ResourceManager.GetString("NaClLoaderFlag", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to NaCl.

-        /// </summary>

-        internal static string NaClPlatformName {

-            get {

-                return ResourceManager.GetString("NaClPlatformName", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to nacl64.exe.

-        /// </summary>

-        internal static string NaClProcessName {

-            get {

-                return ResourceManager.GetString("NaClProcessName", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to PPAPI.

-        /// </summary>

-        internal static string PepperPlatformName {

-            get {

-                return ResourceManager.GetString("PepperPlatformName", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to --register-pepper-plugins=&quot;{0};application/x-nacl&quot;.

-        /// </summary>

-        internal static string PepperProcessPluginFlagFormat {

-            get {

-                return ResourceManager.GetString("PepperProcessPluginFlagFormat", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to NACL_SDK_ROOT.

-        /// </summary>

-        internal static string SDKPathEnvironmentVariable {

-            get {

-                return ResourceManager.GetString("SDKPathEnvironmentVariable", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to NaCl SDK Root is not set in project properties! Cannot run NaCl functionality..

-        /// </summary>

-        internal static string SDKPathNotSetError {

-            get {

-                return ResourceManager.GetString("SDKPathNotSetError", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Unsupported breakpoint type: {0}.

-        /// </summary>

-        internal static string UnsupportedBreakpointTypeFormat {

-            get {

-                return ResourceManager.GetString("UnsupportedBreakpointTypeFormat", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Native Client Web Server Output.

-        /// </summary>

-        internal static string WebServerOutputWindowTitle {

-            get {

-                return ResourceManager.GetString("WebServerOutputWindowTitle", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Specified web server port was not valid, defaulting to {0}.

-        /// </summary>

-        internal static string WebServerPortNotSetFormat {

-            get {

-                return ResourceManager.GetString("WebServerPortNotSetFormat", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Warning: Failed to start web server. Is python.exe in PATH?.

-        /// </summary>

-        internal static string WebServerStartFail {

-            get {

-                return ResourceManager.GetString("WebServerStartFail", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Launching web server....

-        /// </summary>

-        internal static string WebServerStartMessage {

-            get {

-                return ResourceManager.GetString("WebServerStartMessage", resourceCulture);

-            }

-        }

-        

-        /// <summary>

-        ///   Looks up a localized string similar to Killing web server....

-        /// </summary>

-        internal static string WebServerStopMessage {

-            get {

-                return ResourceManager.GetString("WebServerStopMessage", resourceCulture);

-            }

-        }

-    }

-}

+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.269
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace NativeClientVSAddIn {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Strings {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Strings() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NativeClientVSAddIn.Strings", typeof(Strings).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Native Client Visual Studio Add-In.
+        /// </summary>
+        internal static string AddInName {
+            get {
+                return ResourceManager.GetString("AddInName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to CHROME_PATH.
+        /// </summary>
+        internal static string ChromePathEnvironmentVariable {
+            get {
+                return ResourceManager.GetString("ChromePathEnvironmentVariable", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to chrome.exe.
+        /// </summary>
+        internal static string ChromeProcessName {
+            get {
+                return ResourceManager.GetString("ChromeProcessName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to --type=renderer.
+        /// </summary>
+        internal static string ChromeRendererFlag {
+            get {
+                return ResourceManager.GetString("ChromeRendererFlag", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Warning: Multiple start-up projects not supported. Web server will only be run from first project directory.
+        /// </summary>
+        internal static string MultiStartProjectWarning {
+            get {
+                return ResourceManager.GetString("MultiStartProjectWarning", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to --enable-nacl-debug.
+        /// </summary>
+        internal static string NaClDebugFlag {
+            get {
+                return ResourceManager.GetString("NaClDebugFlag", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to --type=nacl-loader.
+        /// </summary>
+        internal static string NaClLoaderFlag {
+            get {
+                return ResourceManager.GetString("NaClLoaderFlag", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to NaCl.
+        /// </summary>
+        internal static string NaClPlatformName {
+            get {
+                return ResourceManager.GetString("NaClPlatformName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to nacl64.exe.
+        /// </summary>
+        internal static string NaClProcessName {
+            get {
+                return ResourceManager.GetString("NaClProcessName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to PPAPI.
+        /// </summary>
+        internal static string PepperPlatformName {
+            get {
+                return ResourceManager.GetString("PepperPlatformName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to --register-pepper-plugins=&quot;{0};application/x-nacl&quot;.
+        /// </summary>
+        internal static string PepperProcessPluginFlagFormat {
+            get {
+                return ResourceManager.GetString("PepperProcessPluginFlagFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to NACL_SDK_ROOT.
+        /// </summary>
+        internal static string SDKPathEnvironmentVariable {
+            get {
+                return ResourceManager.GetString("SDKPathEnvironmentVariable", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to NaCl SDK Root is not set in project properties! Cannot run NaCl functionality..
+        /// </summary>
+        internal static string SDKPathNotSetError {
+            get {
+                return ResourceManager.GetString("SDKPathNotSetError", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Unsupported breakpoint type: {0}.
+        /// </summary>
+        internal static string UnsupportedBreakpointTypeFormat {
+            get {
+                return ResourceManager.GetString("UnsupportedBreakpointTypeFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Native Client Web Server Output.
+        /// </summary>
+        internal static string WebServerOutputWindowTitle {
+            get {
+                return ResourceManager.GetString("WebServerOutputWindowTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Specified web server port was not valid, defaulting to {0}.
+        /// </summary>
+        internal static string WebServerPortNotSetFormat {
+            get {
+                return ResourceManager.GetString("WebServerPortNotSetFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Warning: Failed to start web server. Is python.exe in PATH?.
+        /// </summary>
+        internal static string WebServerStartFail {
+            get {
+                return ResourceManager.GetString("WebServerStartFail", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Launching web server....
+        /// </summary>
+        internal static string WebServerStartMessage {
+            get {
+                return ResourceManager.GetString("WebServerStartMessage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Killing web server....
+        /// </summary>
+        internal static string WebServerStopMessage {
+            get {
+                return ResourceManager.GetString("WebServerStopMessage", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/NativeClientVSAddIn/Utility.cs b/NativeClientVSAddIn/Utility.cs
index 69eec0f..94dff83 100644
--- a/NativeClientVSAddIn/Utility.cs
+++ b/NativeClientVSAddIn/Utility.cs
@@ -1,220 +1,220 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace NativeClientVSAddIn

-{

-  using System;

-  using System.Collections.Generic;

-

-  using EnvDTE;

-  using EnvDTE80;

-  using Microsoft.VisualStudio.VCProjectEngine;

-

-  /// <summary>

-  /// Contains helper functions for this add-in.

-  /// </summary>

-  public static class Utility

-  {

-    /// <summary>

-    /// Tells us if the given project is a Visual C/C++ project.

-    /// </summary>

-    /// <param name="proj">Project to check.</param>

-    /// <returns>True if project is a Visual C/C++ project.</returns>

-    public static bool IsVisualCProject(Project proj)

-    {

-      foreach (Property prop in proj.Properties)

-      {

-        if (prop.Name == "Kind")

-        {

-          string projectType = prop.Value as string;

-          return projectType == "VCProject";

-        }

-      }

-

-      return false;

-    }

-

-    /// <summary>

-    /// Given a generic project, checks that it is a Visual C project, and

-    /// extracts the active VCConfiguration object.

-    /// </summary>

-    /// <param name="proj">Generic project object.</param>

-    /// <returns>The active configuration, or null if failure.</returns>

-    public static VCConfiguration GetActiveVCConfiguration(Project proj)

-    {

-      if (!IsVisualCProject(proj))

-      {

-        return null;

-      }

-

-      VCProject vcproj = (VCProject)proj.Object;

-      IVCCollection configs = vcproj.Configurations;

-      Configuration active = proj.ConfigurationManager.ActiveConfiguration;

-

-      foreach (VCConfiguration config in configs)

-      {

-        if (config.ConfigurationName == active.ConfigurationName &&

-            config.Platform.Name == active.PlatformName)

-        {

-          return config;

-        }

-      }

-

-      return null;

-    }

-

-    /// <summary>

-    /// Will print a message to the web server output pane.

-    /// </summary>

-    /// <param name="dte">The main visual studio interface.</param>

-    /// <param name="message">Message to print to the output pane.</param>

-    public static void WebServerWriteLine(DTE2 dte, string message)

-    {

-      try

-      {

-        OutputWindowPane pane = dte.ToolWindows.OutputWindow.OutputWindowPanes.Item(

-            Strings.WebServerOutputWindowTitle);

-        pane.OutputString(message + "\n");

-      }

-      catch (ArgumentException)

-      {

-        // This exception is expected if the window pane hasn't been created yet.

-      }

-    }

-

-    /// <summary>

-    /// Returns all VCConfigurations from the open solution that have the specified platform name.

-    /// Note only VC++ projects are checked.

-    /// </summary>

-    /// <param name="dte">Visual studio main interface.</param>

-    /// <param name="platformName">Name of the platform to get.</param>

-    /// <returns>List of all matching VCConfigurations.</returns>

-    public static List<VCConfiguration> GetPlatformVCConfigurations(DTE2 dte, string platformName)

-    {

-      var platformConfigs = new List<VCConfiguration>();

-      foreach (Project proj in dte.Solution.Projects)

-      {

-        if (Utility.IsVisualCProject(proj))

-        {

-          VCProject vcproj = (VCProject)proj.Object;

-          IVCCollection configs = vcproj.Configurations;

-

-          foreach (VCConfiguration config in configs)

-          {

-            if (platformName.Equals(config.Platform.Name))

-            {

-              platformConfigs.Add(config);

-            }

-          }

-        }

-      }

-

-      return platformConfigs;

-    }

-

-    /// <summary>

-    /// Extends the string class to allow checking if a string contains another string

-    /// allowing a comparison type (such as case-insensitivity).

-    /// </summary>

-    /// <param name="source">Base string to search.</param>

-    /// <param name="toCheck">String to check if contained within base string.</param>

-    /// <param name="comparison">Comparison type.</param>

-    /// <returns>True if toCheck is contained in source.</returns>

-    public static bool Contains(this string source, string toCheck, StringComparison comparison)

-    {

-      return source.IndexOf(toCheck, comparison) != -1;

-    }

-

-    /// <summary>

-    /// This checks if the first argument is a descendant of the second, where

-    /// both arguments are process IDs of two processes.

-    /// </summary>

-    /// <param name="processSearcher">Process searcher object.</param>

-    /// <param name="descendant">Process ID of the descendant.</param>

-    /// <param name="ancestor">Process ID of ancestor.</param>

-    /// <returns>True if descendant is a descendant of ancestor.</returns>

-    public static bool IsDescendantOfProcess(

-      ProcessSearcher processSearcher,

-      uint descendant,

-      uint ancestor)

-    {

-      return IsDescendantOfProcessHelper(

-          processSearcher,

-          descendant,

-          ancestor,

-          DateTime.UtcNow);

-    }

-

-    /// <summary>

-    /// Helper function to properly dispose of a process object and ensure it is dead.  The given

-    /// reference is set to null afterwards.

-    /// </summary>

-    /// <param name="process">Process to kill.  Reference is set to null afterwards.</param>

-    public static void EnsureProcessKill(ref System.Diagnostics.Process process)

-    {

-      if (process == null)

-      {

-        return;

-      }

-

-      try

-      {

-        process.Kill();

-      }

-      catch (System.InvalidOperationException)

-      {

-        // This happens if the process has already exited.

-      }

-      

-      process.Dispose();

-      process = null;

-    }

-

-    /// <summary>

-    /// Helper function for IsDescendantOfProcessHelper().

-    /// This function prevents an edge case where a process has a parent process ID

-    /// that refers to a descendant of itself. This can occur when the parent of a process

-    /// is destroyed and the parent's pid is recycled and reused on a descendant.  The

-    /// parent process ID value is never updated when the parent is destroyed. The solution

-    /// is to make sure that parents are created before children, otherwise it is a cycle.

-    /// </summary>

-    /// <param name="processSearcher">Process searcher object.</param>

-    /// <param name="descendant">Process ID of the descendant.</param>

-    /// <param name="anscestor">Process ID of the ancestor.</param>

-    /// <param name="previousCreationTime">Creation time of the previous call's descendant.</param>

-    /// <returns>True if descendant is a descendant of ancestor.</returns>

-    private static bool IsDescendantOfProcessHelper(

-        ProcessSearcher processSearcher,

-        uint descendant,

-        uint anscestor,

-        DateTime previousCreationTime)

-    {

-      List<ProcessInfo> results = processSearcher.GetResultsByID(descendant);

-      foreach (ProcessInfo proc in results)

-      {

-        // Ensure this parent relationship is valid.

-        if (proc.CreationDate <= previousCreationTime)

-        {

-          if (descendant == anscestor)

-          {

-            return true;

-          }

-          else if (descendant == proc.ParentID)

-          {

-            // If process is its own parent then we have a cycle, return false.

-            return false;

-          }

-

-          return IsDescendantOfProcessHelper(

-              processSearcher,

-              proc.ParentID,

-              anscestor,

-              proc.CreationDate);

-        }

-      }

-

-      return false;

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace NativeClientVSAddIn
+{
+  using System;
+  using System.Collections.Generic;
+
+  using EnvDTE;
+  using EnvDTE80;
+  using Microsoft.VisualStudio.VCProjectEngine;
+
+  /// <summary>
+  /// Contains helper functions for this add-in.
+  /// </summary>
+  public static class Utility
+  {
+    /// <summary>
+    /// Tells us if the given project is a Visual C/C++ project.
+    /// </summary>
+    /// <param name="proj">Project to check.</param>
+    /// <returns>True if project is a Visual C/C++ project.</returns>
+    public static bool IsVisualCProject(Project proj)
+    {
+      foreach (Property prop in proj.Properties)
+      {
+        if (prop.Name == "Kind")
+        {
+          string projectType = prop.Value as string;
+          return projectType == "VCProject";
+        }
+      }
+
+      return false;
+    }
+
+    /// <summary>
+    /// Given a generic project, checks that it is a Visual C project, and
+    /// extracts the active VCConfiguration object.
+    /// </summary>
+    /// <param name="proj">Generic project object.</param>
+    /// <returns>The active configuration, or null if failure.</returns>
+    public static VCConfiguration GetActiveVCConfiguration(Project proj)
+    {
+      if (!IsVisualCProject(proj))
+      {
+        return null;
+      }
+
+      VCProject vcproj = (VCProject)proj.Object;
+      IVCCollection configs = vcproj.Configurations;
+      Configuration active = proj.ConfigurationManager.ActiveConfiguration;
+
+      foreach (VCConfiguration config in configs)
+      {
+        if (config.ConfigurationName == active.ConfigurationName &&
+            config.Platform.Name == active.PlatformName)
+        {
+          return config;
+        }
+      }
+
+      return null;
+    }
+
+    /// <summary>
+    /// Will print a message to the web server output pane.
+    /// </summary>
+    /// <param name="dte">The main visual studio interface.</param>
+    /// <param name="message">Message to print to the output pane.</param>
+    public static void WebServerWriteLine(DTE2 dte, string message)
+    {
+      try
+      {
+        OutputWindowPane pane = dte.ToolWindows.OutputWindow.OutputWindowPanes.Item(
+            Strings.WebServerOutputWindowTitle);
+        pane.OutputString(message + "\n");
+      }
+      catch (ArgumentException)
+      {
+        // This exception is expected if the window pane hasn't been created yet.
+      }
+    }
+
+    /// <summary>
+    /// Returns all VCConfigurations from the open solution that have the specified platform name.
+    /// Note only VC++ projects are checked.
+    /// </summary>
+    /// <param name="dte">Visual studio main interface.</param>
+    /// <param name="platformName">Name of the platform to get.</param>
+    /// <returns>List of all matching VCConfigurations.</returns>
+    public static List<VCConfiguration> GetPlatformVCConfigurations(DTE2 dte, string platformName)
+    {
+      var platformConfigs = new List<VCConfiguration>();
+      foreach (Project proj in dte.Solution.Projects)
+      {
+        if (Utility.IsVisualCProject(proj))
+        {
+          VCProject vcproj = (VCProject)proj.Object;
+          IVCCollection configs = vcproj.Configurations;
+
+          foreach (VCConfiguration config in configs)
+          {
+            if (platformName.Equals(config.Platform.Name))
+            {
+              platformConfigs.Add(config);
+            }
+          }
+        }
+      }
+
+      return platformConfigs;
+    }
+
+    /// <summary>
+    /// Extends the string class to allow checking if a string contains another string
+    /// allowing a comparison type (such as case-insensitivity).
+    /// </summary>
+    /// <param name="source">Base string to search.</param>
+    /// <param name="toCheck">String to check if contained within base string.</param>
+    /// <param name="comparison">Comparison type.</param>
+    /// <returns>True if toCheck is contained in source.</returns>
+    public static bool Contains(this string source, string toCheck, StringComparison comparison)
+    {
+      return source.IndexOf(toCheck, comparison) != -1;
+    }
+
+    /// <summary>
+    /// This checks if the first argument is a descendant of the second, where
+    /// both arguments are process IDs of two processes.
+    /// </summary>
+    /// <param name="processSearcher">Process searcher object.</param>
+    /// <param name="descendant">Process ID of the descendant.</param>
+    /// <param name="ancestor">Process ID of ancestor.</param>
+    /// <returns>True if descendant is a descendant of ancestor.</returns>
+    public static bool IsDescendantOfProcess(
+      ProcessSearcher processSearcher,
+      uint descendant,
+      uint ancestor)
+    {
+      return IsDescendantOfProcessHelper(
+          processSearcher,
+          descendant,
+          ancestor,
+          DateTime.UtcNow);
+    }
+
+    /// <summary>
+    /// Helper function to properly dispose of a process object and ensure it is dead.  The given
+    /// reference is set to null afterwards.
+    /// </summary>
+    /// <param name="process">Process to kill.  Reference is set to null afterwards.</param>
+    public static void EnsureProcessKill(ref System.Diagnostics.Process process)
+    {
+      if (process == null)
+      {
+        return;
+      }
+
+      try
+      {
+        process.Kill();
+      }
+      catch (System.InvalidOperationException)
+      {
+        // This happens if the process has already exited.
+      }
+      
+      process.Dispose();
+      process = null;
+    }
+
+    /// <summary>
+    /// Helper function for IsDescendantOfProcessHelper().
+    /// This function prevents an edge case where a process has a parent process ID
+    /// that refers to a descendant of itself. This can occur when the parent of a process
+    /// is destroyed and the parent's pid is recycled and reused on a descendant.  The
+    /// parent process ID value is never updated when the parent is destroyed. The solution
+    /// is to make sure that parents are created before children, otherwise it is a cycle.
+    /// </summary>
+    /// <param name="processSearcher">Process searcher object.</param>
+    /// <param name="descendant">Process ID of the descendant.</param>
+    /// <param name="anscestor">Process ID of the ancestor.</param>
+    /// <param name="previousCreationTime">Creation time of the previous call's descendant.</param>
+    /// <returns>True if descendant is a descendant of ancestor.</returns>
+    private static bool IsDescendantOfProcessHelper(
+        ProcessSearcher processSearcher,
+        uint descendant,
+        uint anscestor,
+        DateTime previousCreationTime)
+    {
+      List<ProcessInfo> results = processSearcher.GetResultsByID(descendant);
+      foreach (ProcessInfo proc in results)
+      {
+        // Ensure this parent relationship is valid.
+        if (proc.CreationDate <= previousCreationTime)
+        {
+          if (descendant == anscestor)
+          {
+            return true;
+          }
+          else if (descendant == proc.ParentID)
+          {
+            // If process is its own parent then we have a cycle, return false.
+            return false;
+          }
+
+          return IsDescendantOfProcessHelper(
+              processSearcher,
+              proc.ParentID,
+              anscestor,
+              proc.CreationDate);
+        }
+      }
+
+      return false;
+    }
+  }
+}
diff --git a/NativeClientVSAddIn/WebServer.cs b/NativeClientVSAddIn/WebServer.cs
index 152a944..f60a582 100644
--- a/NativeClientVSAddIn/WebServer.cs
+++ b/NativeClientVSAddIn/WebServer.cs
@@ -1,142 +1,142 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace NativeClientVSAddIn

-{

-  using System;

-

-  using EnvDTE;

-  using Microsoft.VisualStudio.VCProjectEngine;

-

-  /// <summary>

-  /// This class contains the functionality related to the web server which hosts the web page

-  /// during debugging.

-  /// </summary>

-  public class WebServer : IDisposable

-  {

-    /// <summary>

-    /// The web server port to default to if the user does not specify one.

-    /// </summary>

-    private const int DefaultWebServerPort = 5103;

-

-    /// <summary>

-    /// Holds the main web server process.

-    /// </summary>

-    private System.Diagnostics.Process webServer_;

-

-    /// <summary>

-    /// Captures output from the web server.

-    /// </summary>

-    private OutputWindowPane webServerOutputPane_;

-

-    /// <summary>

-    /// Keeps track of if dispose has been called.

-    /// </summary>

-    private bool disposed_ = false;

-

-    /// <summary>

-    /// Constructs the WebServer, starts the web server process.

-    /// </summary>

-    /// <param name="outputWindowPane">Existing output pane to send web server output to.</param>

-    /// <param name="properties">PropertyManager that is set to a valid project/platform.</param>

-    public WebServer(OutputWindowPane outputWindowPane, PropertyManager properties)

-    {

-      if (outputWindowPane == null)

-      {

-        throw new ArgumentNullException("outputWindowPane");

-      }

-

-      if (properties == null)

-      {

-        throw new ArgumentNullException("properties");

-      }

-

-      webServerOutputPane_ = outputWindowPane;

-

-      // Read port from properties, if invalid port then set to default value.

-      int webServerPort;

-      if (!int.TryParse(properties.WebServerPort, out webServerPort))

-      {

-        webServerPort = DefaultWebServerPort;

-      }

-

-      string webServerExecutable = "python.exe";

-      string webServerArguments = string.Format(

-          "{0}\\examples\\httpd.py --no_dir_check {1}", properties.SDKRootDirectory, webServerPort);

-

-      // Start the web server process.

-      try

-      {

-        webServer_ = new System.Diagnostics.Process();

-        webServer_.StartInfo.CreateNoWindow = true;

-        webServer_.StartInfo.UseShellExecute = false;

-        webServer_.StartInfo.RedirectStandardOutput = true;

-        webServer_.StartInfo.RedirectStandardError = true;

-        webServer_.StartInfo.FileName = webServerExecutable;

-        webServer_.StartInfo.Arguments = webServerArguments;

-        webServer_.StartInfo.WorkingDirectory = properties.ProjectDirectory;

-        webServer_.OutputDataReceived += WebServerMessageReceive;

-        webServer_.ErrorDataReceived += WebServerMessageReceive;

-        webServer_.Start();

-        webServer_.BeginOutputReadLine();

-        webServer_.BeginErrorReadLine();

-      }

-      catch (Exception e)

-      {

-        webServerOutputPane_.OutputString(Strings.WebServerStartFail + "\n");

-        webServerOutputPane_.OutputString("Exception: " + e.Message + "\n");

-        webServerOutputPane_.Activate();

-      }

-

-      webServerOutputPane_.Clear();

-      webServerOutputPane_.OutputString(Strings.WebServerStartMessage + "\n");

-      webServerOutputPane_.Activate();

-    }

-

-    /// <summary>

-    /// Finalizer. Should clean up unmanaged resources. Should not be overriden in derived classes.

-    /// </summary>

-    ~WebServer()

-    {

-      Dispose(false);

-    }

-

-    /// <summary>

-    /// Disposes the object when called by user code (not directly by garbage collector).

-    /// </summary>

-    public void Dispose()

-    {

-      Dispose(true);

-      GC.SuppressFinalize(this);

-    }

-

-    /// <summary>

-    /// Disposes the object. If disposing is false then this has been called by garbage collection,

-    /// and we shouldn't reference managed objects.

-    /// </summary>

-    /// <param name="disposing">True if user called Dispose, false if garbage collection.</param>

-    protected virtual void Dispose(bool disposing)

-    {

-      if (!disposed_ && disposing)

-      {

-        // Managed resource clean up.

-        Utility.EnsureProcessKill(ref webServer_);

-        webServerOutputPane_.OutputString(Strings.WebServerStopMessage);

-        webServerOutputPane_.Activate();

-      }

-

-      disposed_ = true;

-    }

-

-    /// <summary>

-    /// Receives output from the web server process to display in the Visual Studio UI.

-    /// </summary>

-    /// <param name="sender">The parameter is not used.</param>

-    /// <param name="e">Contains the data to display.</param>

-    private void WebServerMessageReceive(object sender, System.Diagnostics.DataReceivedEventArgs e)

-    {

-      webServerOutputPane_.OutputString(e.Data + "\n");

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace NativeClientVSAddIn
+{
+  using System;
+
+  using EnvDTE;
+  using Microsoft.VisualStudio.VCProjectEngine;
+
+  /// <summary>
+  /// This class contains the functionality related to the web server which hosts the web page
+  /// during debugging.
+  /// </summary>
+  public class WebServer : IDisposable
+  {
+    /// <summary>
+    /// The web server port to default to if the user does not specify one.
+    /// </summary>
+    private const int DefaultWebServerPort = 5103;
+
+    /// <summary>
+    /// Holds the main web server process.
+    /// </summary>
+    private System.Diagnostics.Process webServer_;
+
+    /// <summary>
+    /// Captures output from the web server.
+    /// </summary>
+    private OutputWindowPane webServerOutputPane_;
+
+    /// <summary>
+    /// Keeps track of if dispose has been called.
+    /// </summary>
+    private bool disposed_ = false;
+
+    /// <summary>
+    /// Constructs the WebServer, starts the web server process.
+    /// </summary>
+    /// <param name="outputWindowPane">Existing output pane to send web server output to.</param>
+    /// <param name="properties">PropertyManager that is set to a valid project/platform.</param>
+    public WebServer(OutputWindowPane outputWindowPane, PropertyManager properties)
+    {
+      if (outputWindowPane == null)
+      {
+        throw new ArgumentNullException("outputWindowPane");
+      }
+
+      if (properties == null)
+      {
+        throw new ArgumentNullException("properties");
+      }
+
+      webServerOutputPane_ = outputWindowPane;
+
+      // Read port from properties, if invalid port then set to default value.
+      int webServerPort;
+      if (!int.TryParse(properties.WebServerPort, out webServerPort))
+      {
+        webServerPort = DefaultWebServerPort;
+      }
+
+      string webServerExecutable = "python.exe";
+      string webServerArguments = string.Format(
+          "{0}\\examples\\httpd.py --no_dir_check {1}", properties.SDKRootDirectory, webServerPort);
+
+      // Start the web server process.
+      try
+      {
+        webServer_ = new System.Diagnostics.Process();
+        webServer_.StartInfo.CreateNoWindow = true;
+        webServer_.StartInfo.UseShellExecute = false;
+        webServer_.StartInfo.RedirectStandardOutput = true;
+        webServer_.StartInfo.RedirectStandardError = true;
+        webServer_.StartInfo.FileName = webServerExecutable;
+        webServer_.StartInfo.Arguments = webServerArguments;
+        webServer_.StartInfo.WorkingDirectory = properties.ProjectDirectory;
+        webServer_.OutputDataReceived += WebServerMessageReceive;
+        webServer_.ErrorDataReceived += WebServerMessageReceive;
+        webServer_.Start();
+        webServer_.BeginOutputReadLine();
+        webServer_.BeginErrorReadLine();
+      }
+      catch (Exception e)
+      {
+        webServerOutputPane_.OutputString(Strings.WebServerStartFail + "\n");
+        webServerOutputPane_.OutputString("Exception: " + e.Message + "\n");
+        webServerOutputPane_.Activate();
+      }
+
+      webServerOutputPane_.Clear();
+      webServerOutputPane_.OutputString(Strings.WebServerStartMessage + "\n");
+      webServerOutputPane_.Activate();
+    }
+
+    /// <summary>
+    /// Finalizer. Should clean up unmanaged resources. Should not be overriden in derived classes.
+    /// </summary>
+    ~WebServer()
+    {
+      Dispose(false);
+    }
+
+    /// <summary>
+    /// Disposes the object when called by user code (not directly by garbage collector).
+    /// </summary>
+    public void Dispose()
+    {
+      Dispose(true);
+      GC.SuppressFinalize(this);
+    }
+
+    /// <summary>
+    /// Disposes the object. If disposing is false then this has been called by garbage collection,
+    /// and we shouldn't reference managed objects.
+    /// </summary>
+    /// <param name="disposing">True if user called Dispose, false if garbage collection.</param>
+    protected virtual void Dispose(bool disposing)
+    {
+      if (!disposed_ && disposing)
+      {
+        // Managed resource clean up.
+        Utility.EnsureProcessKill(ref webServer_);
+        webServerOutputPane_.OutputString(Strings.WebServerStopMessage);
+        webServerOutputPane_.Activate();
+      }
+
+      disposed_ = true;
+    }
+
+    /// <summary>
+    /// Receives output from the web server process to display in the Visual Studio UI.
+    /// </summary>
+    /// <param name="sender">The parameter is not used.</param>
+    /// <param name="e">Contains the data to display.</param>
+    private void WebServerMessageReceive(object sender, System.Diagnostics.DataReceivedEventArgs e)
+    {
+      webServerOutputPane_.OutputString(e.Data + "\n");
+    }
+  }
+}
diff --git a/TestingProjects/BlankValidSolution/NotNaCl/Program.cs b/TestingProjects/BlankValidSolution/NotNaCl/Program.cs
index f45a93f..41c5030 100644
--- a/TestingProjects/BlankValidSolution/NotNaCl/Program.cs
+++ b/TestingProjects/BlankValidSolution/NotNaCl/Program.cs
@@ -1,14 +1,14 @@
-namespace NotNaCl

-{

-  /// <summary>

-  /// This project is used in tests to ensure that the add-in doesn't run

-  /// when a non-NaCl/Pepper project is the start-up project, and that non-NaCl/pepper

-  /// projects still compile correctly when part of a solution containing NaCl projects.

-  /// </summary>

-  class Program

-  {

-    static void Main(string[] args)

-    {

-    }

-  }

-}

+namespace NotNaCl
+{
+  /// <summary>
+  /// This project is used in tests to ensure that the add-in doesn't run
+  /// when a non-NaCl/Pepper project is the start-up project, and that non-NaCl/pepper
+  /// projects still compile correctly when part of a solution containing NaCl projects.
+  /// </summary>
+  class Program
+  {
+    static void Main(string[] args)
+    {
+    }
+  }
+}
diff --git a/UnitTests/ComMessageFilter.cs b/UnitTests/ComMessageFilter.cs
index ae616c3..b90d1d3 100644
--- a/UnitTests/ComMessageFilter.cs
+++ b/UnitTests/ComMessageFilter.cs
@@ -1,161 +1,161 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace UnitTests

-{

-  using System;

-  using System.Runtime.InteropServices;

-

-  /// <summary>

-  /// Interface for IOleMessageFilter.

-  /// </summary>

-  [ComImport, Guid("00000016-0000-0000-C000-000000000046"),

-  InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]

-  public interface IOleMessageFilter

-  {

-    /// <summary>

-    /// Handles calls for the thread.

-    /// </summary>

-    /// <param name="dwCallType">The parameter is not used.</param>

-    /// <param name="hTaskCaller">The parameter is not used.</param>

-    /// <param name="dwTickCount">The parameter is not used.</param>

-    /// <param name="lpInterfaceInfo">The parameter is not used.</param>

-    /// <returns>Code indicating message was handled.</returns>

-    [System.Diagnostics.CodeAnalysis.SuppressMessage(

-      "Microsoft.StyleCop.CSharp.NamingRules",

-      "SA1305:FieldNamesMustNotUseHungarianNotation",

-      Justification = "Matching variable name to COM interface")]

-    [PreserveSig]

-    int HandleInComingCall(

-        int dwCallType,

-        IntPtr hTaskCaller,

-        int dwTickCount,

-        IntPtr lpInterfaceInfo);

-

-    /// <summary>

-    /// Automatically retries the failed call.

-    /// </summary>

-    /// <param name="hTaskCallee">The parameter is not used.</param>

-    /// <param name="dwTickCount">The parameter is not used.</param>

-    /// <param name="dwRejectType">The parameter is not used.</param>

-    /// <returns>Code indicating call should be retried.</returns>

-    [System.Diagnostics.CodeAnalysis.SuppressMessage(

-      "Microsoft.StyleCop.CSharp.NamingRules",

-      "SA1305:FieldNamesMustNotUseHungarianNotation",

-      Justification = "Matching variable name to COM interface")]

-    [PreserveSig]

-    int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType);

-

-    /// <summary>

-    /// Handles an incoming message by indicating it should be dispatched always.

-    /// </summary>

-    /// <param name="hTaskCallee">The parameter is not used.</param>

-    /// <param name="dwTickCount">The parameter is not used.</param>

-    /// <param name="dwPendingType">The parameter is not used.</param>

-    /// <returns>Code indicating message should be dispatched.</returns>

-    [System.Diagnostics.CodeAnalysis.SuppressMessage(

-      "Microsoft.StyleCop.CSharp.NamingRules",

-      "SA1305:FieldNamesMustNotUseHungarianNotation",

-      Justification = "Matching variable name to COM interface")]

-    [PreserveSig]

-    int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType);

-  }

-

-  /// <summary>

-  /// This class receives messages from the COM calls to Visual Studio

-  /// and auto-retries them if they fail because VS is busy.

-  /// </summary>

-  public class ComMessageFilter : IOleMessageFilter

-  {

-    /// <summary>

-    /// Note this registers the filter only for the current thread.

-    /// </summary>

-    public static void Register()

-    {

-      IOleMessageFilter oldFilter = null;

-      CoRegisterMessageFilter(new ComMessageFilter(), out oldFilter);

-    }

-

-    /// <summary>

-    /// Note this only closes the filter for the current thread.

-    /// </summary>

-    public static void Revoke()

-    {

-      IOleMessageFilter oldFilter = null;

-      CoRegisterMessageFilter(null, out oldFilter);

-    }

-

-    /// <summary>

-    /// Handles calls for the thread.

-    /// </summary>

-    /// <param name="dwCallType">The parameter is not used.</param>

-    /// <param name="hTaskCaller">The parameter is not used.</param>

-    /// <param name="dwTickCount">The parameter is not used.</param>

-    /// <param name="lpInterfaceInfo">The parameter is not used.</param>

-    /// <returns>Code indicating message was handled.</returns>

-    [System.Diagnostics.CodeAnalysis.SuppressMessage(

-      "Microsoft.StyleCop.CSharp.NamingRules",

-      "SA1305:FieldNamesMustNotUseHungarianNotation",

-      Justification = "Matching variable name to COM interface")]

-    int IOleMessageFilter.HandleInComingCall(

-        int dwCallType,

-        System.IntPtr hTaskCaller,

-        int dwTickCount,

-        System.IntPtr lpInterfaceInfo)

-    {

-      return 0;  // SERVERCALL_ISHANDLED.

-    }

-

-    /// <summary>

-    /// Automatically retries the failed call.

-    /// </summary>

-    /// <param name="hTaskCallee">The parameter is not used.</param>

-    /// <param name="dwTickCount">The parameter is not used.</param>

-    /// <param name="dwRejectType">The parameter is not used.</param>

-    /// <returns>Code indicating call should be retried.</returns>

-    [System.Diagnostics.CodeAnalysis.SuppressMessage(

-      "Microsoft.StyleCop.CSharp.NamingRules",

-      "SA1305:FieldNamesMustNotUseHungarianNotation",

-      Justification = "Matching variable name to COM interface")]

-    int IOleMessageFilter.RetryRejectedCall(

-        System.IntPtr hTaskCallee,

-        int dwTickCount,

-        int dwRejectType)

-    {

-      // If reject type is SERVERCALL_RETRYLATER.

-      if (dwRejectType == 2)

-      {

-        // Immediate retry.

-        return 99;

-      }

-

-      // Cancel call.

-      return -1;

-    }

-

-    /// <summary>

-    /// Handles an incoming message by indicating it should be dispatched always.

-    /// </summary>

-    /// <param name="hTaskCallee">The parameter is not used.</param>

-    /// <param name="dwTickCount">The parameter is not used.</param>

-    /// <param name="dwPendingType">The parameter is not used.</param>

-    /// <returns>Code indicating message should be dispatched.</returns>

-    [System.Diagnostics.CodeAnalysis.SuppressMessage(

-      "Microsoft.StyleCop.CSharp.NamingRules",

-      "SA1305:FieldNamesMustNotUseHungarianNotation",

-      Justification = "Matching variable name to COM interface")]

-    int IOleMessageFilter.MessagePending(

-        System.IntPtr hTaskCallee, 

-        int dwTickCount,

-        int dwPendingType)

-    {

-      return 2; // PENDINGMSG_WAITDEFPROCESS.

-    }

-

-    // Implement the IOleMessageFilter interface.

-    [DllImport("Ole32.dll")]

-    private static extern int CoRegisterMessageFilter(

-        IOleMessageFilter newFilter, out IOleMessageFilter oldFilter);

-  }

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace UnitTests
+{
+  using System;
+  using System.Runtime.InteropServices;
+
+  /// <summary>
+  /// Interface for IOleMessageFilter.
+  /// </summary>
+  [ComImport, Guid("00000016-0000-0000-C000-000000000046"),
+  InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+  public interface IOleMessageFilter
+  {
+    /// <summary>
+    /// Handles calls for the thread.
+    /// </summary>
+    /// <param name="dwCallType">The parameter is not used.</param>
+    /// <param name="hTaskCaller">The parameter is not used.</param>
+    /// <param name="dwTickCount">The parameter is not used.</param>
+    /// <param name="lpInterfaceInfo">The parameter is not used.</param>
+    /// <returns>Code indicating message was handled.</returns>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage(
+      "Microsoft.StyleCop.CSharp.NamingRules",
+      "SA1305:FieldNamesMustNotUseHungarianNotation",
+      Justification = "Matching variable name to COM interface")]
+    [PreserveSig]
+    int HandleInComingCall(
+        int dwCallType,
+        IntPtr hTaskCaller,
+        int dwTickCount,
+        IntPtr lpInterfaceInfo);
+
+    /// <summary>
+    /// Automatically retries the failed call.
+    /// </summary>
+    /// <param name="hTaskCallee">The parameter is not used.</param>
+    /// <param name="dwTickCount">The parameter is not used.</param>
+    /// <param name="dwRejectType">The parameter is not used.</param>
+    /// <returns>Code indicating call should be retried.</returns>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage(
+      "Microsoft.StyleCop.CSharp.NamingRules",
+      "SA1305:FieldNamesMustNotUseHungarianNotation",
+      Justification = "Matching variable name to COM interface")]
+    [PreserveSig]
+    int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType);
+
+    /// <summary>
+    /// Handles an incoming message by indicating it should be dispatched always.
+    /// </summary>
+    /// <param name="hTaskCallee">The parameter is not used.</param>
+    /// <param name="dwTickCount">The parameter is not used.</param>
+    /// <param name="dwPendingType">The parameter is not used.</param>
+    /// <returns>Code indicating message should be dispatched.</returns>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage(
+      "Microsoft.StyleCop.CSharp.NamingRules",
+      "SA1305:FieldNamesMustNotUseHungarianNotation",
+      Justification = "Matching variable name to COM interface")]
+    [PreserveSig]
+    int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType);
+  }
+
+  /// <summary>
+  /// This class receives messages from the COM calls to Visual Studio
+  /// and auto-retries them if they fail because VS is busy.
+  /// </summary>
+  public class ComMessageFilter : IOleMessageFilter
+  {
+    /// <summary>
+    /// Note this registers the filter only for the current thread.
+    /// </summary>
+    public static void Register()
+    {
+      IOleMessageFilter oldFilter = null;
+      CoRegisterMessageFilter(new ComMessageFilter(), out oldFilter);
+    }
+
+    /// <summary>
+    /// Note this only closes the filter for the current thread.
+    /// </summary>
+    public static void Revoke()
+    {
+      IOleMessageFilter oldFilter = null;
+      CoRegisterMessageFilter(null, out oldFilter);
+    }
+
+    /// <summary>
+    /// Handles calls for the thread.
+    /// </summary>
+    /// <param name="dwCallType">The parameter is not used.</param>
+    /// <param name="hTaskCaller">The parameter is not used.</param>
+    /// <param name="dwTickCount">The parameter is not used.</param>
+    /// <param name="lpInterfaceInfo">The parameter is not used.</param>
+    /// <returns>Code indicating message was handled.</returns>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage(
+      "Microsoft.StyleCop.CSharp.NamingRules",
+      "SA1305:FieldNamesMustNotUseHungarianNotation",
+      Justification = "Matching variable name to COM interface")]
+    int IOleMessageFilter.HandleInComingCall(
+        int dwCallType,
+        System.IntPtr hTaskCaller,
+        int dwTickCount,
+        System.IntPtr lpInterfaceInfo)
+    {
+      return 0;  // SERVERCALL_ISHANDLED.
+    }
+
+    /// <summary>
+    /// Automatically retries the failed call.
+    /// </summary>
+    /// <param name="hTaskCallee">The parameter is not used.</param>
+    /// <param name="dwTickCount">The parameter is not used.</param>
+    /// <param name="dwRejectType">The parameter is not used.</param>
+    /// <returns>Code indicating call should be retried.</returns>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage(
+      "Microsoft.StyleCop.CSharp.NamingRules",
+      "SA1305:FieldNamesMustNotUseHungarianNotation",
+      Justification = "Matching variable name to COM interface")]
+    int IOleMessageFilter.RetryRejectedCall(
+        System.IntPtr hTaskCallee,
+        int dwTickCount,
+        int dwRejectType)
+    {
+      // If reject type is SERVERCALL_RETRYLATER.
+      if (dwRejectType == 2)
+      {
+        // Immediate retry.
+        return 99;
+      }
+
+      // Cancel call.
+      return -1;
+    }
+
+    /// <summary>
+    /// Handles an incoming message by indicating it should be dispatched always.
+    /// </summary>
+    /// <param name="hTaskCallee">The parameter is not used.</param>
+    /// <param name="dwTickCount">The parameter is not used.</param>
+    /// <param name="dwPendingType">The parameter is not used.</param>
+    /// <returns>Code indicating message should be dispatched.</returns>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage(
+      "Microsoft.StyleCop.CSharp.NamingRules",
+      "SA1305:FieldNamesMustNotUseHungarianNotation",
+      Justification = "Matching variable name to COM interface")]
+    int IOleMessageFilter.MessagePending(
+        System.IntPtr hTaskCallee, 
+        int dwTickCount,
+        int dwPendingType)
+    {
+      return 2; // PENDINGMSG_WAITDEFPROCESS.
+    }
+
+    // Implement the IOleMessageFilter interface.
+    [DllImport("Ole32.dll")]
+    private static extern int CoRegisterMessageFilter(
+        IOleMessageFilter newFilter, out IOleMessageFilter oldFilter);
+  }
 }
\ No newline at end of file
diff --git a/UnitTests/MockProcessSearcher.cs b/UnitTests/MockProcessSearcher.cs
index 5cb9827..3ca346d 100644
--- a/UnitTests/MockProcessSearcher.cs
+++ b/UnitTests/MockProcessSearcher.cs
@@ -1,36 +1,36 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace UnitTests

-{

-  using System.Collections.Generic;

-

-  /// <summary>

-  /// A fake process searcher that allows the list of 'processes' on the system to be faked.

-  /// </summary>

-  public class MockProcessSearcher : NativeClientVSAddIn.ProcessSearcher

-  {

-    /// <summary>

-    /// Constructs the fake process searcher.

-    /// </summary>

-    public MockProcessSearcher()

-    {

-      this.ProcessList = new List<NativeClientVSAddIn.ProcessInfo>();

-    }

-

-    /// <summary>

-    /// Gets or sets the fake list of processes this MockProcessSearcher knows about.

-    /// </summary>

-    public List<NativeClientVSAddIn.ProcessInfo> ProcessList { get; set; }

-

-    /// <summary>

-    /// This method substitutes the fake process list for the list of real system processes.

-    /// </summary>

-    /// <returns>Fake list of processes</returns>

-    protected override List<NativeClientVSAddIn.ProcessInfo> GetSystemProcesses()

-    {

-      return this.ProcessList;

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace UnitTests
+{
+  using System.Collections.Generic;
+
+  /// <summary>
+  /// A fake process searcher that allows the list of 'processes' on the system to be faked.
+  /// </summary>
+  public class MockProcessSearcher : NativeClientVSAddIn.ProcessSearcher
+  {
+    /// <summary>
+    /// Constructs the fake process searcher.
+    /// </summary>
+    public MockProcessSearcher()
+    {
+      this.ProcessList = new List<NativeClientVSAddIn.ProcessInfo>();
+    }
+
+    /// <summary>
+    /// Gets or sets the fake list of processes this MockProcessSearcher knows about.
+    /// </summary>
+    public List<NativeClientVSAddIn.ProcessInfo> ProcessList { get; set; }
+
+    /// <summary>
+    /// This method substitutes the fake process list for the list of real system processes.
+    /// </summary>
+    /// <returns>Fake list of processes</returns>
+    protected override List<NativeClientVSAddIn.ProcessInfo> GetSystemProcesses()
+    {
+      return this.ProcessList;
+    }
+  }
+}
diff --git a/UnitTests/MockPropertyManager.cs b/UnitTests/MockPropertyManager.cs
index b156aad..7189150 100644
--- a/UnitTests/MockPropertyManager.cs
+++ b/UnitTests/MockPropertyManager.cs
@@ -1,117 +1,117 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace NativeClientVSAddIn

-{

-  using System;

-

-  /// <summary>

-  /// This class fakes the mechanism for reading and writing properties on property pages.

-  /// </summary>

-  public class MockPropertyManager : PropertyManager

-  {

-    /// <summary>

-    /// Relays property get calls to the provided delegate.

-    /// </summary>

-    private PropertyGetter getter_;

-

-    /// <summary>

-    /// Relays property set calls to the provided delegate.

-    /// </summary>

-    private PropertySetter setter_;

-

-    /// <summary>

-    /// Constructs the property manager.

-    /// </summary>

-    /// <param name="platformType">The platform type to represent.</param>

-    /// <param name="getter">Receives property get requests and returns mock values.</param>

-    /// <param name="setter">Receives property set requests and checks them.</param>

-    public MockPropertyManager(

-        ProjectPlatformType platformType, PropertyGetter getter, PropertySetter setter)

-    {

-      this.ProjectPlatform = platformType;

-      getter_ = getter;

-      setter_ = setter;

-    }

-

-    /// <summary>

-    /// Can be used to capture the property requests and return whatever value is desired.

-    /// If this returns null then the test will throw an error that the property was unexpected.

-    /// </summary>

-    /// <param name="page">Property page name.</param>

-    /// <param name="name">Property name.</param>

-    /// <returns>Value to return. Should return null if property was unexpected.</returns>

-    public delegate string PropertyGetter(string page, string name);

-

-    /// <summary>

-    /// Can be used to capture the property requests and set whatever value is desired or do checks.

-    /// If this returns false then the test will throw an error that the property was unexpected.

-    /// </summary>

-    /// <param name="page">Property page name.</param>

-    /// <param name="name">Property name.</param>

-    /// <param name="value">Value to set.</param>

-    /// <returns>True if the value was expected, false if unexpected (error).</returns>

-    public delegate bool PropertySetter(string page, string name, string value);

-

-    /// <summary>

-    /// The full path to the output assembly.

-    /// </summary>

-    public override string PluginAssembly

-    {

-      get { return getter_("Property", "PluginAssembly"); }

-      protected set { setter_("Property", "PluginAssembly", value); }

-    }

-

-    /// <summary>

-    /// The main project directory.

-    /// </summary>

-    public override string ProjectDirectory

-    {

-      get { return getter_("Property", "ProjectDirectory"); }

-      protected set { setter_("Property", "ProjectDirectory", value); }

-    }

-

-    /// <summary>

-    /// The directory where the output assembly is placed.

-    /// </summary>

-    public override string OutputDirectory

-    {

-      get { return getter_("Property", "OutputDirectory"); }

-      protected set { setter_("Property", "OutputDirectory", value); }

-    }

-

-    /// <summary>

-    /// Reads any generic property from the current target properties.

-    /// </summary>

-    /// <param name="page">Name of the page where the property is located.</param>

-    /// <param name="name">Name of the property.</param>

-    /// <returns>Mock value of the property as returned by the getter_.</returns>

-    public override string GetProperty(string page, string name)

-    {

-      string value = getter_(page, name);

-      if (value == null)

-      {

-        throw new Exception(string.Format(

-            "Property request not expected by test! Page: {0}, Prop: {1}", page, name));

-      }

-

-      return value;

-    }

-

-    /// <summary>

-    /// Sets any generic property to the current target properties.

-    /// </summary>

-    /// <param name="page">Page where property is located.</param>

-    /// <param name="name">Name of the property.</param>

-    /// <param name="value">Unevaluated string value to set.</param>

-    public override void SetProperty(string page, string name, string value)

-    {

-      if (!setter_(page, name, value))

-      {

-        throw new Exception(string.Format(

-            "Property set request was not expected by test! Page {0}, Prop: {1}", page, name));

-      }

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace NativeClientVSAddIn
+{
+  using System;
+
+  /// <summary>
+  /// This class fakes the mechanism for reading and writing properties on property pages.
+  /// </summary>
+  public class MockPropertyManager : PropertyManager
+  {
+    /// <summary>
+    /// Relays property get calls to the provided delegate.
+    /// </summary>
+    private PropertyGetter getter_;
+
+    /// <summary>
+    /// Relays property set calls to the provided delegate.
+    /// </summary>
+    private PropertySetter setter_;
+
+    /// <summary>
+    /// Constructs the property manager.
+    /// </summary>
+    /// <param name="platformType">The platform type to represent.</param>
+    /// <param name="getter">Receives property get requests and returns mock values.</param>
+    /// <param name="setter">Receives property set requests and checks them.</param>
+    public MockPropertyManager(
+        ProjectPlatformType platformType, PropertyGetter getter, PropertySetter setter)
+    {
+      this.ProjectPlatform = platformType;
+      getter_ = getter;
+      setter_ = setter;
+    }
+
+    /// <summary>
+    /// Can be used to capture the property requests and return whatever value is desired.
+    /// If this returns null then the test will throw an error that the property was unexpected.
+    /// </summary>
+    /// <param name="page">Property page name.</param>
+    /// <param name="name">Property name.</param>
+    /// <returns>Value to return. Should return null if property was unexpected.</returns>
+    public delegate string PropertyGetter(string page, string name);
+
+    /// <summary>
+    /// Can be used to capture the property requests and set whatever value is desired or do checks.
+    /// If this returns false then the test will throw an error that the property was unexpected.
+    /// </summary>
+    /// <param name="page">Property page name.</param>
+    /// <param name="name">Property name.</param>
+    /// <param name="value">Value to set.</param>
+    /// <returns>True if the value was expected, false if unexpected (error).</returns>
+    public delegate bool PropertySetter(string page, string name, string value);
+
+    /// <summary>
+    /// The full path to the output assembly.
+    /// </summary>
+    public override string PluginAssembly
+    {
+      get { return getter_("Property", "PluginAssembly"); }
+      protected set { setter_("Property", "PluginAssembly", value); }
+    }
+
+    /// <summary>
+    /// The main project directory.
+    /// </summary>
+    public override string ProjectDirectory
+    {
+      get { return getter_("Property", "ProjectDirectory"); }
+      protected set { setter_("Property", "ProjectDirectory", value); }
+    }
+
+    /// <summary>
+    /// The directory where the output assembly is placed.
+    /// </summary>
+    public override string OutputDirectory
+    {
+      get { return getter_("Property", "OutputDirectory"); }
+      protected set { setter_("Property", "OutputDirectory", value); }
+    }
+
+    /// <summary>
+    /// Reads any generic property from the current target properties.
+    /// </summary>
+    /// <param name="page">Name of the page where the property is located.</param>
+    /// <param name="name">Name of the property.</param>
+    /// <returns>Mock value of the property as returned by the getter_.</returns>
+    public override string GetProperty(string page, string name)
+    {
+      string value = getter_(page, name);
+      if (value == null)
+      {
+        throw new Exception(string.Format(
+            "Property request not expected by test! Page: {0}, Prop: {1}", page, name));
+      }
+
+      return value;
+    }
+
+    /// <summary>
+    /// Sets any generic property to the current target properties.
+    /// </summary>
+    /// <param name="page">Page where property is located.</param>
+    /// <param name="name">Name of the property.</param>
+    /// <param name="value">Unevaluated string value to set.</param>
+    public override void SetProperty(string page, string name, string value)
+    {
+      if (!setter_(page, name, value))
+      {
+        throw new Exception(string.Format(
+            "Property set request was not expected by test! Page {0}, Prop: {1}", page, name));
+      }
+    }
+  }
+}
diff --git a/UnitTests/PluginDebuggerGDBTest.cs b/UnitTests/PluginDebuggerGDBTest.cs
index 6f54d08..9a85d90 100644
--- a/UnitTests/PluginDebuggerGDBTest.cs
+++ b/UnitTests/PluginDebuggerGDBTest.cs
@@ -1,398 +1,398 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace UnitTests

-{

-  using System;

-  using System.Collections.Generic;

-  using System.IO;

-  using System.Reflection;

-

-  using EnvDTE80;

-  using Microsoft.VisualStudio.TestTools.UnitTesting;

-

-  using NativeClientVSAddIn;

-    

-  /// <summary>

-  /// This is a test class for PluginDebuggerGDBTest and is intended

-  /// to contain all PluginDebuggerGDB Unit Tests

-  /// </summary>

-  [TestClass]

-  public class PluginDebuggerGDBTest

-  {

-    /// <summary>

-    /// This holds the path to the NaCl solution used in these tests.

-    /// The NaCl solution is a valid nacl/pepper plug-in VS solution.

-    /// It is copied into the testing deployment directory and opened in some tests.

-    /// Because unit-tests run in any order, the solution should not be written to

-    /// in any tests.

-    /// </summary>

-    private static string naclSolution;

-

-    /// <summary>

-    /// The main visual studio object.

-    /// </summary>

-    private DTE2 dte_;

-

-    /// <summary>

-    /// Holds the default properties from property pages to use during tests.

-    /// </summary>

-    private MockPropertyManager properties_;

-

-    /// <summary>

-    /// Gets or sets the test context which provides information about,

-    /// and functionality for the current test run.

-    /// </summary>

-    public TestContext TestContext { get; set; }

-

-    /// <summary>

-    /// This is run one time before any test methods are called. Here we set-up a test-copy of a

-    /// new NaCl solution for use in the tests.

-    /// </summary>

-    /// <param name="testContext">Holds information about the current test run</param>

-    [ClassInitialize]

-    public static void ClassSetup(TestContext testContext)

-    {

-      DTE2 dte = TestUtilities.StartVisualStudioInstance();

-      try

-      {

-        naclSolution = TestUtilities.CreateBlankValidNaClSolution(

-          dte,

-          "PluginDebuggerGDBTest",

-          NativeClientVSAddIn.Strings.PepperPlatformName,

-          NativeClientVSAddIn.Strings.NaClPlatformName,

-          testContext);

-      }

-      finally

-      {

-        TestUtilities.CleanUpVisualStudioInstance(dte);

-      }

-    }

-

-    /// <summary>

-    /// This is run before each test to create test resources.

-    /// </summary>

-    [TestInitialize]

-    public void TestSetup()

-    {

-      dte_ = TestUtilities.StartVisualStudioInstance();

-      try

-      {

-        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);

-      }

-      catch

-      {

-        TestUtilities.CleanUpVisualStudioInstance(dte_);

-        throw;

-      }

-

-      // Set up mock property manager to return the desired property values.

-      properties_ = new MockPropertyManager(

-        PropertyManager.ProjectPlatformType.NaCl,

-        delegate(string page, string name)

-        {

-          switch (page)

-          {

-            case "ConfigurationGeneral":

-              switch (name)

-              {

-                case "VSNaClSDKRoot": return System.Environment.GetEnvironmentVariable(

-                    NativeClientVSAddIn.Strings.SDKPathEnvironmentVariable);

-                case "NaClIrtPath": return @"fake\Irt\Path";

-                case "NaClManifestPath": return string.Empty;

-                case "ToolchainName": return "newlib";

-              }

-

-              break;

-            case "Property":

-              switch (name)

-              {

-                case "ProjectDirectory": return TestContext.DeploymentDirectory;

-                case "PluginAssembly": return @"fake\Assembly\String";

-              }

-

-              break;

-          }

-

-          return null;

-        },

-        null);

-    }

-

-    /// <summary>

-    /// This is run after each test to clean up things created in TestSetup().

-    /// </summary>

-    [TestCleanup]

-    public void TestCleanup()

-    {

-      TestUtilities.CleanUpVisualStudioInstance(dte_);

-    }

-

-    /// <summary>

-    /// A test for the constructor.

-    /// </summary>

-    [TestMethod]

-    public void PluginDebuggerGDBConstructorTest()

-    {

-      // Check that a null dte fails.

-      try

-      {

-        PluginDebuggerBase nullDte = new PluginDebuggerGDB(null, properties_);

-        Assert.Fail("Using null DTE instance did not throw exception");

-      }

-      catch (ArgumentNullException)

-      {

-        // This is expected for a correct implementation.

-      }

-      catch

-      {

-        Assert.Fail("Using null DTE instance threw something other than ArgumentNullException");

-      }

-

-      // Check that a null PropertyManager fails.

-      try

-      {

-        PluginDebuggerBase nullDte = new PluginDebuggerGDB(dte_, null);

-        Assert.Fail("Using null property manager did not throw exception");

-      }

-      catch (ArgumentNullException)

-      {

-        // This is expected for a correct implementation.

-      }

-      catch

-      {

-        Assert.Fail("Using null property manager threw something other than ArgumentNullException");

-      }

-    }

-

-    /// <summary>

-    /// Tests that a plugin can be found.

-    /// </summary>

-    [TestMethod]

-    [DeploymentItem("NativeClientVSAddIn.dll")]

-    public void FindAndAttachToNaClPluginTest()

-    {

-      MockProcessSearcher processResults = new MockProcessSearcher();

-

-      using (PluginDebuggerGDB target = new PluginDebuggerGDB(dte_, properties_))

-      {

-        PluginDebuggerBase_Accessor targetBase = new PluginDebuggerBase_Accessor(

-            new PrivateObject(target, new PrivateType(typeof(PluginDebuggerBase))));

-        targetBase.debuggedChromeMainProcess_ = System.Diagnostics.Process.GetCurrentProcess();

-

-        uint currentProcId = (uint)targetBase.debuggedChromeMainProcess_.Id;

-

-        // Target nacl process flag.

-        string naclCommandLine = Strings.NaClLoaderFlag;

-

-        // Fake the list of processes on the system.

-        processResults.ProcessList.Add(

-            new ProcessInfo(

-                currentProcId,

-                currentProcId,

-                string.Empty,

-                Strings.NaClDebugFlag,

-                Strings.ChromeProcessName));

-        processResults.ProcessList.Add(

-            new ProcessInfo(1, currentProcId, string.Empty, string.Empty, "MyParentProcess"));

-        processResults.ProcessList.Add(

-            new ProcessInfo(11, 1, string.Empty, naclCommandLine, Strings.NaClProcessName));

-

-        // This is missing some relevant command line args, should not be attached to.

-        processResults.ProcessList.Add(

-            new ProcessInfo(13, 1, string.Empty, string.Empty, Strings.NaClProcessName));

-

-        // This doesn't have chrome process as their parent, so they should not be attached to.

-        processResults.ProcessList.Add(

-            new ProcessInfo(15, 15, string.Empty, naclCommandLine, Strings.NaClProcessName));

-

-        // Set the private value to the mock object (can't use accessor since no valid cast).

-        FieldInfo processSearcherField = typeof(PluginDebuggerBase).GetField(

-            "processSearcher_",

-            BindingFlags.NonPublic | BindingFlags.Instance);

-        processSearcherField.SetValue(targetBase.Target, processResults);

-

-        // Test that the correct processes are attached to.

-        bool goodNaCl = false;

-        var handler = new EventHandler<NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs>(

-          delegate(object unused, NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs args)

-          {

-            switch (args.ProcessID)

-            {

-              case 11:

-                if (goodNaCl)

-                {

-                  Assert.Fail("Should not attach twice to same nacl process");

-                }

-

-                goodNaCl = true;

-                break;

-              case 13:

-                Assert.Fail("Should not attach to nacl process with bad args");

-                break;

-              case 15:

-                Assert.Fail("Should not attach to nacl process that is not "

-                          + "descendant of Visual Studio");

-                break;

-              default:

-                Assert.Fail("Should not attach to non-pepper/non-nacl process");

-                break;

-            }

-          });

-

-        target.PluginFoundEvent += handler;

-        target.FindAndAttachToPlugin(null, null);

-        target.PluginFoundEvent -= handler;

-

-        Assert.IsTrue(goodNaCl, "Failed to attach to NaCl process");

-      }

-    }

-

-    /// <summary>

-    /// A test for Attach. Implicitly tests CleanUpGDBProcess().

-    /// </summary>

-    [TestMethod]

-    [DeploymentItem("NativeClientVSAddIn.dll")]

-    public void AttachNaClGDBTest()

-    {

-      PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, properties_);

-

-      string existingGDB = "AttachNaClGDBTest_existingGDB";

-      try

-      {

-        target.gdbProcess_ = TestUtilities.StartProcessForKilling(existingGDB, 20);

-        string existingInitFileName = Path.GetTempFileName();

-        target.gdbInitFileName_ = existingInitFileName;

-

-        // Visual studio won't allow adding a breakpoint unless it is associated with

-        // an existing file and valid line number, so use BlankValidSolution.

-        dte_.Solution.Open(naclSolution);

-        string fileName = "main.cpp";

-        string functionName = "NaClProjectInstance::HandleMessage";

-        int lineNumber = 39;

-        dte_.Debugger.Breakpoints.Add(Function: functionName);

-        dte_.Debugger.Breakpoints.Add(Line: lineNumber, File: fileName);

-

-        target.Attach(null, new PluginDebuggerBase.PluginFoundEventArgs(0));

-

-        Assert.IsTrue(File.Exists(target.gdbInitFileName_), "Init file not written");

-

-        var gdbCommands = new List<string>(File.ReadAllLines(target.gdbInitFileName_));

-

-        // Validate that the commands contain what we specified.

-        // The syntax itself is not validated since this add-in is not responsible for

-        // the syntax and it could change.

-        Assert.IsTrue(

-            gdbCommands.Exists(s => s.Contains(fileName) && s.Contains(lineNumber.ToString())),

-            "Line breakpoint not properly set");

-        Assert.IsTrue(

-            gdbCommands.Exists(s => s.Contains(functionName)),

-            "Function breakpoint not properly set");

-        

-        // Note fake assembly string should be double escaped when passed to gdb.

-        Assert.IsTrue(

-          gdbCommands.Exists(s => s.Contains(functionName)),

-          @"fake\\Assembly\\String");

-

-        // Check that the pre-existing gdb process was killed and its init file cleaned up.

-        Assert.IsFalse(

-            TestUtilities.DoesProcessExist("python.exe", existingGDB),

-            "Failed to kill existing GDB process");

-        Assert.IsFalse(

-            File.Exists(existingInitFileName),

-            "Failed to delete existing temp gdb init file");

-      }

-      finally

-      {

-        if (dte_.Debugger.Breakpoints != null)

-        {

-          // Remove all breakpoints.

-          foreach (EnvDTE.Breakpoint bp in dte_.Debugger.Breakpoints)

-          {

-            bp.Delete();

-          }

-        }

-

-        // Clean up file if not erased.

-        if (!string.IsNullOrEmpty(target.gdbInitFileName_) && File.Exists(target.gdbInitFileName_))

-        {

-          File.Delete(target.gdbInitFileName_);

-        }

-

-        // Kill the gdb process if not killed.

-        if (target.gdbProcess_ != null && !target.gdbProcess_.HasExited)

-        {

-          target.gdbProcess_.Kill();

-          target.gdbProcess_.Dispose();

-        }

-      }

-    }

-

-    /// <summary>

-    /// A test for Dispose. Implicitly tests CleanUpGDBProcess().

-    /// </summary>

-    [TestMethod]

-    [DeploymentItem("NativeClientVSAddIn.dll")]

-    public void DisposeTest()

-    {

-      PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, properties_);

-

-      string existingGDB = "DisposeTest_GDB";

-      try

-      {

-        target.gdbProcess_ = TestUtilities.StartProcessForKilling(existingGDB, 20);

-        string existingInitFileName = Path.GetTempFileName();

-        target.gdbInitFileName_ = existingInitFileName;

-

-        target.Dispose();

-        

-        // Check that the pre-existing gdb process was killed and its init file cleaned up.

-        Assert.IsFalse(

-            TestUtilities.DoesProcessExist("python.exe", existingGDB),

-            "Failed to kill existing GDB process");

-        Assert.IsFalse(

-            File.Exists(existingInitFileName),

-            "Failed to delete existing temp gdb init file");

-      }

-      finally

-      {

-        // Clean up file if not erased.

-        if (!string.IsNullOrEmpty(target.gdbInitFileName_) && File.Exists(target.gdbInitFileName_))

-        {

-          File.Delete(target.gdbInitFileName_);

-        }

-

-        // Kill the gdb process if not killed.

-        if (target.gdbProcess_ != null && !target.gdbProcess_.HasExited)

-        {

-          target.gdbProcess_.Kill();

-          target.gdbProcess_.Dispose();

-        }

-      }

-    }

-

-    /// <summary>

-    /// A test for IsPluginProcess.

-    /// </summary>

-    [TestMethod]

-    [DeploymentItem("NativeClientVSAddIn.dll")]

-    public void IsNaClPluginProcessTest()

-    {

-      PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, properties_);

-

-      ProcessInfo badProc = new ProcessInfo(

-          1, 1, string.Empty, Strings.ChromeRendererFlag, Strings.NaClProcessName);

-      ProcessInfo goodProc = new ProcessInfo(

-          1, 1, string.Empty, Strings.NaClLoaderFlag, Strings.NaClProcessName);

-      

-      string goodMainChromeFlags = Strings.NaClDebugFlag;

-      string badMainChromeFlags = string.Format(

-          Strings.PepperProcessPluginFlagFormat, target.pluginAssembly_);

-

-      Assert.IsTrue(target.IsPluginProcess(goodProc, goodMainChromeFlags));

-      Assert.IsFalse(target.IsPluginProcess(goodProc, badMainChromeFlags));

-      Assert.IsFalse(target.IsPluginProcess(badProc, goodMainChromeFlags));

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace UnitTests
+{
+  using System;
+  using System.Collections.Generic;
+  using System.IO;
+  using System.Reflection;
+
+  using EnvDTE80;
+  using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+  using NativeClientVSAddIn;
+    
+  /// <summary>
+  /// This is a test class for PluginDebuggerGDBTest and is intended
+  /// to contain all PluginDebuggerGDB Unit Tests
+  /// </summary>
+  [TestClass]
+  public class PluginDebuggerGDBTest
+  {
+    /// <summary>
+    /// This holds the path to the NaCl solution used in these tests.
+    /// The NaCl solution is a valid nacl/pepper plug-in VS solution.
+    /// It is copied into the testing deployment directory and opened in some tests.
+    /// Because unit-tests run in any order, the solution should not be written to
+    /// in any tests.
+    /// </summary>
+    private static string naclSolution;
+
+    /// <summary>
+    /// The main visual studio object.
+    /// </summary>
+    private DTE2 dte_;
+
+    /// <summary>
+    /// Holds the default properties from property pages to use during tests.
+    /// </summary>
+    private MockPropertyManager properties_;
+
+    /// <summary>
+    /// Gets or sets the test context which provides information about,
+    /// and functionality for the current test run.
+    /// </summary>
+    public TestContext TestContext { get; set; }
+
+    /// <summary>
+    /// This is run one time before any test methods are called. Here we set-up a test-copy of a
+    /// new NaCl solution for use in the tests.
+    /// </summary>
+    /// <param name="testContext">Holds information about the current test run</param>
+    [ClassInitialize]
+    public static void ClassSetup(TestContext testContext)
+    {
+      DTE2 dte = TestUtilities.StartVisualStudioInstance();
+      try
+      {
+        naclSolution = TestUtilities.CreateBlankValidNaClSolution(
+          dte,
+          "PluginDebuggerGDBTest",
+          NativeClientVSAddIn.Strings.PepperPlatformName,
+          NativeClientVSAddIn.Strings.NaClPlatformName,
+          testContext);
+      }
+      finally
+      {
+        TestUtilities.CleanUpVisualStudioInstance(dte);
+      }
+    }
+
+    /// <summary>
+    /// This is run before each test to create test resources.
+    /// </summary>
+    [TestInitialize]
+    public void TestSetup()
+    {
+      dte_ = TestUtilities.StartVisualStudioInstance();
+      try
+      {
+        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);
+      }
+      catch
+      {
+        TestUtilities.CleanUpVisualStudioInstance(dte_);
+        throw;
+      }
+
+      // Set up mock property manager to return the desired property values.
+      properties_ = new MockPropertyManager(
+        PropertyManager.ProjectPlatformType.NaCl,
+        delegate(string page, string name)
+        {
+          switch (page)
+          {
+            case "ConfigurationGeneral":
+              switch (name)
+              {
+                case "VSNaClSDKRoot": return System.Environment.GetEnvironmentVariable(
+                    NativeClientVSAddIn.Strings.SDKPathEnvironmentVariable);
+                case "NaClIrtPath": return @"fake\Irt\Path";
+                case "NaClManifestPath": return string.Empty;
+                case "ToolchainName": return "newlib";
+              }
+
+              break;
+            case "Property":
+              switch (name)
+              {
+                case "ProjectDirectory": return TestContext.DeploymentDirectory;
+                case "PluginAssembly": return @"fake\Assembly\String";
+              }
+
+              break;
+          }
+
+          return null;
+        },
+        null);
+    }
+
+    /// <summary>
+    /// This is run after each test to clean up things created in TestSetup().
+    /// </summary>
+    [TestCleanup]
+    public void TestCleanup()
+    {
+      TestUtilities.CleanUpVisualStudioInstance(dte_);
+    }
+
+    /// <summary>
+    /// A test for the constructor.
+    /// </summary>
+    [TestMethod]
+    public void PluginDebuggerGDBConstructorTest()
+    {
+      // Check that a null dte fails.
+      try
+      {
+        PluginDebuggerBase nullDte = new PluginDebuggerGDB(null, properties_);
+        Assert.Fail("Using null DTE instance did not throw exception");
+      }
+      catch (ArgumentNullException)
+      {
+        // This is expected for a correct implementation.
+      }
+      catch
+      {
+        Assert.Fail("Using null DTE instance threw something other than ArgumentNullException");
+      }
+
+      // Check that a null PropertyManager fails.
+      try
+      {
+        PluginDebuggerBase nullDte = new PluginDebuggerGDB(dte_, null);
+        Assert.Fail("Using null property manager did not throw exception");
+      }
+      catch (ArgumentNullException)
+      {
+        // This is expected for a correct implementation.
+      }
+      catch
+      {
+        Assert.Fail("Using null property manager threw something other than ArgumentNullException");
+      }
+    }
+
+    /// <summary>
+    /// Tests that a plugin can be found.
+    /// </summary>
+    [TestMethod]
+    [DeploymentItem("NativeClientVSAddIn.dll")]
+    public void FindAndAttachToNaClPluginTest()
+    {
+      MockProcessSearcher processResults = new MockProcessSearcher();
+
+      using (PluginDebuggerGDB target = new PluginDebuggerGDB(dte_, properties_))
+      {
+        PluginDebuggerBase_Accessor targetBase = new PluginDebuggerBase_Accessor(
+            new PrivateObject(target, new PrivateType(typeof(PluginDebuggerBase))));
+        targetBase.debuggedChromeMainProcess_ = System.Diagnostics.Process.GetCurrentProcess();
+
+        uint currentProcId = (uint)targetBase.debuggedChromeMainProcess_.Id;
+
+        // Target nacl process flag.
+        string naclCommandLine = Strings.NaClLoaderFlag;
+
+        // Fake the list of processes on the system.
+        processResults.ProcessList.Add(
+            new ProcessInfo(
+                currentProcId,
+                currentProcId,
+                string.Empty,
+                Strings.NaClDebugFlag,
+                Strings.ChromeProcessName));
+        processResults.ProcessList.Add(
+            new ProcessInfo(1, currentProcId, string.Empty, string.Empty, "MyParentProcess"));
+        processResults.ProcessList.Add(
+            new ProcessInfo(11, 1, string.Empty, naclCommandLine, Strings.NaClProcessName));
+
+        // This is missing some relevant command line args, should not be attached to.
+        processResults.ProcessList.Add(
+            new ProcessInfo(13, 1, string.Empty, string.Empty, Strings.NaClProcessName));
+
+        // This doesn't have chrome process as their parent, so they should not be attached to.
+        processResults.ProcessList.Add(
+            new ProcessInfo(15, 15, string.Empty, naclCommandLine, Strings.NaClProcessName));
+
+        // Set the private value to the mock object (can't use accessor since no valid cast).
+        FieldInfo processSearcherField = typeof(PluginDebuggerBase).GetField(
+            "processSearcher_",
+            BindingFlags.NonPublic | BindingFlags.Instance);
+        processSearcherField.SetValue(targetBase.Target, processResults);
+
+        // Test that the correct processes are attached to.
+        bool goodNaCl = false;
+        var handler = new EventHandler<NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs>(
+          delegate(object unused, NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs args)
+          {
+            switch (args.ProcessID)
+            {
+              case 11:
+                if (goodNaCl)
+                {
+                  Assert.Fail("Should not attach twice to same nacl process");
+                }
+
+                goodNaCl = true;
+                break;
+              case 13:
+                Assert.Fail("Should not attach to nacl process with bad args");
+                break;
+              case 15:
+                Assert.Fail("Should not attach to nacl process that is not "
+                          + "descendant of Visual Studio");
+                break;
+              default:
+                Assert.Fail("Should not attach to non-pepper/non-nacl process");
+                break;
+            }
+          });
+
+        target.PluginFoundEvent += handler;
+        target.FindAndAttachToPlugin(null, null);
+        target.PluginFoundEvent -= handler;
+
+        Assert.IsTrue(goodNaCl, "Failed to attach to NaCl process");
+      }
+    }
+
+    /// <summary>
+    /// A test for Attach. Implicitly tests CleanUpGDBProcess().
+    /// </summary>
+    [TestMethod]
+    [DeploymentItem("NativeClientVSAddIn.dll")]
+    public void AttachNaClGDBTest()
+    {
+      PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, properties_);
+
+      string existingGDB = "AttachNaClGDBTest_existingGDB";
+      try
+      {
+        target.gdbProcess_ = TestUtilities.StartProcessForKilling(existingGDB, 20);
+        string existingInitFileName = Path.GetTempFileName();
+        target.gdbInitFileName_ = existingInitFileName;
+
+        // Visual studio won't allow adding a breakpoint unless it is associated with
+        // an existing file and valid line number, so use BlankValidSolution.
+        dte_.Solution.Open(naclSolution);
+        string fileName = "main.cpp";
+        string functionName = "NaClProjectInstance::HandleMessage";
+        int lineNumber = 39;
+        dte_.Debugger.Breakpoints.Add(Function: functionName);
+        dte_.Debugger.Breakpoints.Add(Line: lineNumber, File: fileName);
+
+        target.Attach(null, new PluginDebuggerBase.PluginFoundEventArgs(0));
+
+        Assert.IsTrue(File.Exists(target.gdbInitFileName_), "Init file not written");
+
+        var gdbCommands = new List<string>(File.ReadAllLines(target.gdbInitFileName_));
+
+        // Validate that the commands contain what we specified.
+        // The syntax itself is not validated since this add-in is not responsible for
+        // the syntax and it could change.
+        Assert.IsTrue(
+            gdbCommands.Exists(s => s.Contains(fileName) && s.Contains(lineNumber.ToString())),
+            "Line breakpoint not properly set");
+        Assert.IsTrue(
+            gdbCommands.Exists(s => s.Contains(functionName)),
+            "Function breakpoint not properly set");
+        
+        // Note fake assembly string should be double escaped when passed to gdb.
+        Assert.IsTrue(
+          gdbCommands.Exists(s => s.Contains(functionName)),
+          @"fake\\Assembly\\String");
+
+        // Check that the pre-existing gdb process was killed and its init file cleaned up.
+        Assert.IsFalse(
+            TestUtilities.DoesProcessExist("python.exe", existingGDB),
+            "Failed to kill existing GDB process");
+        Assert.IsFalse(
+            File.Exists(existingInitFileName),
+            "Failed to delete existing temp gdb init file");
+      }
+      finally
+      {
+        if (dte_.Debugger.Breakpoints != null)
+        {
+          // Remove all breakpoints.
+          foreach (EnvDTE.Breakpoint bp in dte_.Debugger.Breakpoints)
+          {
+            bp.Delete();
+          }
+        }
+
+        // Clean up file if not erased.
+        if (!string.IsNullOrEmpty(target.gdbInitFileName_) && File.Exists(target.gdbInitFileName_))
+        {
+          File.Delete(target.gdbInitFileName_);
+        }
+
+        // Kill the gdb process if not killed.
+        if (target.gdbProcess_ != null && !target.gdbProcess_.HasExited)
+        {
+          target.gdbProcess_.Kill();
+          target.gdbProcess_.Dispose();
+        }
+      }
+    }
+
+    /// <summary>
+    /// A test for Dispose. Implicitly tests CleanUpGDBProcess().
+    /// </summary>
+    [TestMethod]
+    [DeploymentItem("NativeClientVSAddIn.dll")]
+    public void DisposeTest()
+    {
+      PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, properties_);
+
+      string existingGDB = "DisposeTest_GDB";
+      try
+      {
+        target.gdbProcess_ = TestUtilities.StartProcessForKilling(existingGDB, 20);
+        string existingInitFileName = Path.GetTempFileName();
+        target.gdbInitFileName_ = existingInitFileName;
+
+        target.Dispose();
+        
+        // Check that the pre-existing gdb process was killed and its init file cleaned up.
+        Assert.IsFalse(
+            TestUtilities.DoesProcessExist("python.exe", existingGDB),
+            "Failed to kill existing GDB process");
+        Assert.IsFalse(
+            File.Exists(existingInitFileName),
+            "Failed to delete existing temp gdb init file");
+      }
+      finally
+      {
+        // Clean up file if not erased.
+        if (!string.IsNullOrEmpty(target.gdbInitFileName_) && File.Exists(target.gdbInitFileName_))
+        {
+          File.Delete(target.gdbInitFileName_);
+        }
+
+        // Kill the gdb process if not killed.
+        if (target.gdbProcess_ != null && !target.gdbProcess_.HasExited)
+        {
+          target.gdbProcess_.Kill();
+          target.gdbProcess_.Dispose();
+        }
+      }
+    }
+
+    /// <summary>
+    /// A test for IsPluginProcess.
+    /// </summary>
+    [TestMethod]
+    [DeploymentItem("NativeClientVSAddIn.dll")]
+    public void IsNaClPluginProcessTest()
+    {
+      PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, properties_);
+
+      ProcessInfo badProc = new ProcessInfo(
+          1, 1, string.Empty, Strings.ChromeRendererFlag, Strings.NaClProcessName);
+      ProcessInfo goodProc = new ProcessInfo(
+          1, 1, string.Empty, Strings.NaClLoaderFlag, Strings.NaClProcessName);
+      
+      string goodMainChromeFlags = Strings.NaClDebugFlag;
+      string badMainChromeFlags = string.Format(
+          Strings.PepperProcessPluginFlagFormat, target.pluginAssembly_);
+
+      Assert.IsTrue(target.IsPluginProcess(goodProc, goodMainChromeFlags));
+      Assert.IsFalse(target.IsPluginProcess(goodProc, badMainChromeFlags));
+      Assert.IsFalse(target.IsPluginProcess(badProc, goodMainChromeFlags));
+    }
+  }
+}
diff --git a/UnitTests/PluginDebuggerVSTest.cs b/UnitTests/PluginDebuggerVSTest.cs
index dd37310..62d5841 100644
--- a/UnitTests/PluginDebuggerVSTest.cs
+++ b/UnitTests/PluginDebuggerVSTest.cs
@@ -1,286 +1,286 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace UnitTests

-{

-  using System;

-  using System.Reflection;

-

-  using EnvDTE80;

-  using Microsoft.VisualStudio.TestTools.UnitTesting;

-

-  using NativeClientVSAddIn;

-

-  /// <summary>

-  /// This is a test class for PluginDebuggerVSTest and is intended

-  /// to contain all PluginDebuggerVS Unit Tests

-  /// </summary>

-  [TestClass]

-  public class PluginDebuggerVSTest

-  {

-    /// <summary>

-    /// The main visual studio object.

-    /// </summary>

-    private DTE2 dte_;

-

-    /// <summary>

-    /// Holds the default properties from property pages to use during tests.

-    /// </summary>

-    private MockPropertyManager properties_;

-

-    /// <summary>

-    /// Gets or sets the test context which provides information about,

-    /// and functionality for the current test run.

-    /// </summary>

-    public TestContext TestContext { get; set; }

-

-    /// <summary>

-    /// This is run before each test to create test resources.

-    /// </summary>

-    [TestInitialize]

-    public void TestSetup()

-    {

-      dte_ = TestUtilities.StartVisualStudioInstance();

-      try

-      {

-        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);

-      }

-      catch

-      {

-        TestUtilities.CleanUpVisualStudioInstance(dte_);

-        throw;

-      }

-

-      // Set up mock property manager to return the desired property values.

-      properties_ = new MockPropertyManager(

-        PropertyManager.ProjectPlatformType.Pepper,

-        delegate(string page, string name)

-        {

-          switch (page)

-          {

-            case "ConfigurationGeneral":

-              switch (name)

-              {

-                case "VSNaClSDKRoot": return System.Environment.GetEnvironmentVariable(

-                    NativeClientVSAddIn.Strings.SDKPathEnvironmentVariable);

-              }

-

-              break;

-            case "Property":

-              switch (name)

-              {

-                case "ProjectDirectory": return TestContext.DeploymentDirectory;

-                case "PluginAssembly": return @"fake\Assembly\String";

-              }

-

-              break;

-          }

-

-          return null;

-        },

-        null);

-    }

-

-    /// <summary>

-    /// This is run after each test to clean up things created in TestSetup().

-    /// </summary>

-    [TestCleanup]

-    public void TestCleanup()

-    {

-      TestUtilities.CleanUpVisualStudioInstance(dte_);

-    }

-

-    /// <summary>

-    /// A test for the constructor.

-    /// </summary>

-    [TestMethod]

-    public void PluginDebuggerVSConstructorTest()

-    {

-      // Check that a null dte fails.

-      try

-      {

-        PluginDebuggerBase nullDte = new PluginDebuggerVS(null, properties_);

-        Assert.Fail("Using null DTE instance did not throw exception");

-      }

-      catch (ArgumentNullException)

-      {

-        // This is expected for a correct implementation.

-      }

-      catch

-      {

-        Assert.Fail("Using null DTE instance threw something other than ArgumentNullException");

-      }

-

-      // Check that a null PropertyManager fails.

-      try

-      {

-        PluginDebuggerBase nullDte = new PluginDebuggerVS(dte_, null);

-        Assert.Fail("Using null property manager did not throw exception");

-      }

-      catch (ArgumentNullException)

-      {

-        // This is expected for a correct implementation.

-      }

-      catch

-      {

-        Assert.Fail("Using null property manager threw something other than ArgumentNullException");

-      }

-    }

-

-    /// <summary>

-    /// A test for FindAndAttachToPlugin.

-    /// </summary>

-    [TestMethod]

-    [DeploymentItem("NativeClientVSAddIn.dll")]

-    public void FindAndAttachToPepperPluginTest()

-    {

-      MockProcessSearcher processResults = new MockProcessSearcher();

-

-      using (PluginDebuggerVS target = new PluginDebuggerVS(dte_, properties_))

-      {

-        PluginDebuggerBase_Accessor targetBase = new PluginDebuggerBase_Accessor(

-            new PrivateObject(target, new PrivateType(typeof(PluginDebuggerBase))));

-        targetBase.debuggedChromeMainProcess_ = System.Diagnostics.Process.GetCurrentProcess();

-        uint currentProcId = (uint)targetBase.debuggedChromeMainProcess_.Id;

-

-        string pluginLoadFlag = string.Format(

-            Strings.PepperProcessPluginFlagFormat, properties_.PluginAssembly);

-        string pepperCommandLine = string.Concat(

-            pluginLoadFlag, " ", Strings.ChromeRendererFlag);

-

-        // Fake the list of processes on the system.

-        processResults.ProcessList.Add(

-            new ProcessInfo(

-                currentProcId,

-                currentProcId,

-                string.Empty,

-                Strings.NaClDebugFlag,

-                Strings.ChromeProcessName));

-        processResults.ProcessList.Add(

-            new ProcessInfo(1, currentProcId, string.Empty, string.Empty, "MyParentProcess"));

-        processResults.ProcessList.Add(

-            new ProcessInfo(10, 1, string.Empty, pepperCommandLine, Strings.ChromeProcessName));

-

-        // This is missing some relevant command line args, and should not be attached to.

-        processResults.ProcessList.Add(

-            new ProcessInfo(12, 1, string.Empty, pluginLoadFlag, Strings.ChromeProcessName));

-

-        // This doesn't have this process as its parent, and should not be attached to.

-        processResults.ProcessList.Add(

-            new ProcessInfo(14, 14, string.Empty, pepperCommandLine, Strings.ChromeProcessName));

-

-        // Set the private value to the mock object (can't use accessor since no valid cast).

-        FieldInfo processSearcherField = typeof(PluginDebuggerBase).GetField(

-            "processSearcher_",

-            BindingFlags.NonPublic | BindingFlags.Instance);

-        processSearcherField.SetValue(targetBase.Target, processResults);

-

-        // Test that the correct processes are attached to.

-        bool goodPepper = false;

-        var handler = new EventHandler<NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs>(

-          delegate(object unused, NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs args)

-          {

-            switch (args.ProcessID)

-            {

-              case 10:

-                if (goodPepper)

-                {

-                  Assert.Fail("Should not attach twice to same pepper process");

-                }

-

-                goodPepper = true;

-                break;

-              case 12:

-                Assert.Fail("Should not attach to pepper process with bad args");

-                break;

-              case 14:

-                Assert.Fail("Should not attach to pepper process that is not "

-                          + "descendant of Visual Studio");

-                break;

-              default:

-                Assert.Fail("Should not attach to non-pepper/non-nacl process");

-                break;

-            }

-          });

-

-        target.PluginFoundEvent += handler;

-        target.FindAndAttachToPlugin(null, null);

-        target.PluginFoundEvent -= handler;

-

-        Assert.IsTrue(goodPepper, "Failed to attach to pepper process");

-      }

-    }

-

-    /// <summary>

-    /// Checks that VS properly attaches debugger.

-    /// </summary>

-    [TestMethod]

-    [DeploymentItem("NativeClientVSAddIn.dll")]

-    public void AttachVSDebuggerTest()

-    {

-      using (System.Diagnostics.Process dummyProc = TestUtilities.StartProcessForKilling(

-          "DummyProc", 20))

-      {

-        try

-        {

-          PluginDebuggerVS_Accessor target = new PluginDebuggerVS_Accessor(dte_, properties_);

-

-          var pluginFoundArgs = new NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs(

-              (uint)dummyProc.Id);

-          target.Attach(null, pluginFoundArgs);

-

-          bool isBeingDebugged = false;

-          foreach (EnvDTE.Process proc in dte_.Debugger.DebuggedProcesses)

-          {

-            if (proc.ProcessID == dummyProc.Id)

-            {

-              isBeingDebugged = true;

-            }

-          }

-

-          Assert.IsTrue(isBeingDebugged, "Visual Studio debugger did not attach");

-        }

-        finally

-        {

-          if (dummyProc != null && !dummyProc.HasExited)

-          {

-            dummyProc.Kill();

-            dummyProc.Dispose();

-          }

-        }

-      }

-    }

-

-    /// <summary>

-    /// A test for IsPluginProcess.

-    /// </summary>

-    [TestMethod]

-    [DeploymentItem("NativeClientVSAddIn.dll")]

-    public void IsPepperPluginProcessTest()

-    {

-      PluginDebuggerVS_Accessor target = new PluginDebuggerVS_Accessor(dte_, properties_);

-

-      string identifierFlagTarget =

-          string.Format(Strings.PepperProcessPluginFlagFormat, target.pluginAssembly_);

-      string goodFlags = string.Concat(Strings.ChromeRendererFlag, ' ', identifierFlagTarget);

-

-      ProcessInfo badProc1 = new ProcessInfo(

-          1, 1, string.Empty, goodFlags, Strings.NaClProcessName);

-      ProcessInfo badProc2 = new ProcessInfo(

-          1, 1, string.Empty, Strings.NaClLoaderFlag, Strings.ChromeProcessName);

-      ProcessInfo badProc3 = new ProcessInfo(

-          1, 1, string.Empty, Strings.ChromeRendererFlag, Strings.ChromeProcessName);

-      ProcessInfo badProc4 = new ProcessInfo(

-          1, 1, string.Empty, identifierFlagTarget, Strings.ChromeProcessName);

-      ProcessInfo goodProc = new ProcessInfo(

-          1, 1, string.Empty, goodFlags, Strings.ChromeProcessName);

-

-      Assert.IsTrue(target.IsPluginProcess(goodProc, string.Empty));

-      Assert.IsFalse(target.IsPluginProcess(badProc1, string.Empty));

-      Assert.IsFalse(target.IsPluginProcess(badProc2, string.Empty));

-      Assert.IsFalse(target.IsPluginProcess(badProc3, string.Empty));

-      Assert.IsFalse(target.IsPluginProcess(badProc4, string.Empty));

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace UnitTests
+{
+  using System;
+  using System.Reflection;
+
+  using EnvDTE80;
+  using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+  using NativeClientVSAddIn;
+
+  /// <summary>
+  /// This is a test class for PluginDebuggerVSTest and is intended
+  /// to contain all PluginDebuggerVS Unit Tests
+  /// </summary>
+  [TestClass]
+  public class PluginDebuggerVSTest
+  {
+    /// <summary>
+    /// The main visual studio object.
+    /// </summary>
+    private DTE2 dte_;
+
+    /// <summary>
+    /// Holds the default properties from property pages to use during tests.
+    /// </summary>
+    private MockPropertyManager properties_;
+
+    /// <summary>
+    /// Gets or sets the test context which provides information about,
+    /// and functionality for the current test run.
+    /// </summary>
+    public TestContext TestContext { get; set; }
+
+    /// <summary>
+    /// This is run before each test to create test resources.
+    /// </summary>
+    [TestInitialize]
+    public void TestSetup()
+    {
+      dte_ = TestUtilities.StartVisualStudioInstance();
+      try
+      {
+        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);
+      }
+      catch
+      {
+        TestUtilities.CleanUpVisualStudioInstance(dte_);
+        throw;
+      }
+
+      // Set up mock property manager to return the desired property values.
+      properties_ = new MockPropertyManager(
+        PropertyManager.ProjectPlatformType.Pepper,
+        delegate(string page, string name)
+        {
+          switch (page)
+          {
+            case "ConfigurationGeneral":
+              switch (name)
+              {
+                case "VSNaClSDKRoot": return System.Environment.GetEnvironmentVariable(
+                    NativeClientVSAddIn.Strings.SDKPathEnvironmentVariable);
+              }
+
+              break;
+            case "Property":
+              switch (name)
+              {
+                case "ProjectDirectory": return TestContext.DeploymentDirectory;
+                case "PluginAssembly": return @"fake\Assembly\String";
+              }
+
+              break;
+          }
+
+          return null;
+        },
+        null);
+    }
+
+    /// <summary>
+    /// This is run after each test to clean up things created in TestSetup().
+    /// </summary>
+    [TestCleanup]
+    public void TestCleanup()
+    {
+      TestUtilities.CleanUpVisualStudioInstance(dte_);
+    }
+
+    /// <summary>
+    /// A test for the constructor.
+    /// </summary>
+    [TestMethod]
+    public void PluginDebuggerVSConstructorTest()
+    {
+      // Check that a null dte fails.
+      try
+      {
+        PluginDebuggerBase nullDte = new PluginDebuggerVS(null, properties_);
+        Assert.Fail("Using null DTE instance did not throw exception");
+      }
+      catch (ArgumentNullException)
+      {
+        // This is expected for a correct implementation.
+      }
+      catch
+      {
+        Assert.Fail("Using null DTE instance threw something other than ArgumentNullException");
+      }
+
+      // Check that a null PropertyManager fails.
+      try
+      {
+        PluginDebuggerBase nullDte = new PluginDebuggerVS(dte_, null);
+        Assert.Fail("Using null property manager did not throw exception");
+      }
+      catch (ArgumentNullException)
+      {
+        // This is expected for a correct implementation.
+      }
+      catch
+      {
+        Assert.Fail("Using null property manager threw something other than ArgumentNullException");
+      }
+    }
+
+    /// <summary>
+    /// A test for FindAndAttachToPlugin.
+    /// </summary>
+    [TestMethod]
+    [DeploymentItem("NativeClientVSAddIn.dll")]
+    public void FindAndAttachToPepperPluginTest()
+    {
+      MockProcessSearcher processResults = new MockProcessSearcher();
+
+      using (PluginDebuggerVS target = new PluginDebuggerVS(dte_, properties_))
+      {
+        PluginDebuggerBase_Accessor targetBase = new PluginDebuggerBase_Accessor(
+            new PrivateObject(target, new PrivateType(typeof(PluginDebuggerBase))));
+        targetBase.debuggedChromeMainProcess_ = System.Diagnostics.Process.GetCurrentProcess();
+        uint currentProcId = (uint)targetBase.debuggedChromeMainProcess_.Id;
+
+        string pluginLoadFlag = string.Format(
+            Strings.PepperProcessPluginFlagFormat, properties_.PluginAssembly);
+        string pepperCommandLine = string.Concat(
+            pluginLoadFlag, " ", Strings.ChromeRendererFlag);
+
+        // Fake the list of processes on the system.
+        processResults.ProcessList.Add(
+            new ProcessInfo(
+                currentProcId,
+                currentProcId,
+                string.Empty,
+                Strings.NaClDebugFlag,
+                Strings.ChromeProcessName));
+        processResults.ProcessList.Add(
+            new ProcessInfo(1, currentProcId, string.Empty, string.Empty, "MyParentProcess"));
+        processResults.ProcessList.Add(
+            new ProcessInfo(10, 1, string.Empty, pepperCommandLine, Strings.ChromeProcessName));
+
+        // This is missing some relevant command line args, and should not be attached to.
+        processResults.ProcessList.Add(
+            new ProcessInfo(12, 1, string.Empty, pluginLoadFlag, Strings.ChromeProcessName));
+
+        // This doesn't have this process as its parent, and should not be attached to.
+        processResults.ProcessList.Add(
+            new ProcessInfo(14, 14, string.Empty, pepperCommandLine, Strings.ChromeProcessName));
+
+        // Set the private value to the mock object (can't use accessor since no valid cast).
+        FieldInfo processSearcherField = typeof(PluginDebuggerBase).GetField(
+            "processSearcher_",
+            BindingFlags.NonPublic | BindingFlags.Instance);
+        processSearcherField.SetValue(targetBase.Target, processResults);
+
+        // Test that the correct processes are attached to.
+        bool goodPepper = false;
+        var handler = new EventHandler<NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs>(
+          delegate(object unused, NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs args)
+          {
+            switch (args.ProcessID)
+            {
+              case 10:
+                if (goodPepper)
+                {
+                  Assert.Fail("Should not attach twice to same pepper process");
+                }
+
+                goodPepper = true;
+                break;
+              case 12:
+                Assert.Fail("Should not attach to pepper process with bad args");
+                break;
+              case 14:
+                Assert.Fail("Should not attach to pepper process that is not "
+                          + "descendant of Visual Studio");
+                break;
+              default:
+                Assert.Fail("Should not attach to non-pepper/non-nacl process");
+                break;
+            }
+          });
+
+        target.PluginFoundEvent += handler;
+        target.FindAndAttachToPlugin(null, null);
+        target.PluginFoundEvent -= handler;
+
+        Assert.IsTrue(goodPepper, "Failed to attach to pepper process");
+      }
+    }
+
+    /// <summary>
+    /// Checks that VS properly attaches debugger.
+    /// </summary>
+    [TestMethod]
+    [DeploymentItem("NativeClientVSAddIn.dll")]
+    public void AttachVSDebuggerTest()
+    {
+      using (System.Diagnostics.Process dummyProc = TestUtilities.StartProcessForKilling(
+          "DummyProc", 20))
+      {
+        try
+        {
+          PluginDebuggerVS_Accessor target = new PluginDebuggerVS_Accessor(dte_, properties_);
+
+          var pluginFoundArgs = new NativeClientVSAddIn.PluginDebuggerBase.PluginFoundEventArgs(
+              (uint)dummyProc.Id);
+          target.Attach(null, pluginFoundArgs);
+
+          bool isBeingDebugged = false;
+          foreach (EnvDTE.Process proc in dte_.Debugger.DebuggedProcesses)
+          {
+            if (proc.ProcessID == dummyProc.Id)
+            {
+              isBeingDebugged = true;
+            }
+          }
+
+          Assert.IsTrue(isBeingDebugged, "Visual Studio debugger did not attach");
+        }
+        finally
+        {
+          if (dummyProc != null && !dummyProc.HasExited)
+          {
+            dummyProc.Kill();
+            dummyProc.Dispose();
+          }
+        }
+      }
+    }
+
+    /// <summary>
+    /// A test for IsPluginProcess.
+    /// </summary>
+    [TestMethod]
+    [DeploymentItem("NativeClientVSAddIn.dll")]
+    public void IsPepperPluginProcessTest()
+    {
+      PluginDebuggerVS_Accessor target = new PluginDebuggerVS_Accessor(dte_, properties_);
+
+      string identifierFlagTarget =
+          string.Format(Strings.PepperProcessPluginFlagFormat, target.pluginAssembly_);
+      string goodFlags = string.Concat(Strings.ChromeRendererFlag, ' ', identifierFlagTarget);
+
+      ProcessInfo badProc1 = new ProcessInfo(
+          1, 1, string.Empty, goodFlags, Strings.NaClProcessName);
+      ProcessInfo badProc2 = new ProcessInfo(
+          1, 1, string.Empty, Strings.NaClLoaderFlag, Strings.ChromeProcessName);
+      ProcessInfo badProc3 = new ProcessInfo(
+          1, 1, string.Empty, Strings.ChromeRendererFlag, Strings.ChromeProcessName);
+      ProcessInfo badProc4 = new ProcessInfo(
+          1, 1, string.Empty, identifierFlagTarget, Strings.ChromeProcessName);
+      ProcessInfo goodProc = new ProcessInfo(
+          1, 1, string.Empty, goodFlags, Strings.ChromeProcessName);
+
+      Assert.IsTrue(target.IsPluginProcess(goodProc, string.Empty));
+      Assert.IsFalse(target.IsPluginProcess(badProc1, string.Empty));
+      Assert.IsFalse(target.IsPluginProcess(badProc2, string.Empty));
+      Assert.IsFalse(target.IsPluginProcess(badProc3, string.Empty));
+      Assert.IsFalse(target.IsPluginProcess(badProc4, string.Empty));
+    }
+  }
+}
diff --git a/UnitTests/Properties/AssemblyInfo.cs b/UnitTests/Properties/AssemblyInfo.cs
index de91dbf..699de28 100644
--- a/UnitTests/Properties/AssemblyInfo.cs
+++ b/UnitTests/Properties/AssemblyInfo.cs
@@ -1,39 +1,39 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-using System.Reflection;

-using System.Runtime.CompilerServices;

-using System.Runtime.InteropServices;

-

-// General Information about an assembly is controlled through the following

-// set of attributes. Change these attribute values to modify the information

-// associated with an assembly.

-[assembly: AssemblyTitle("UnitTests")]

-[assembly: AssemblyDescription("Unit tests for the Native Client Visual Studio Add-in")]

-[assembly: AssemblyConfiguration("")]

-[assembly: AssemblyCompany("Google Inc.")]

-[assembly: AssemblyProduct("UnitTests")]

-[assembly: AssemblyCopyright("Copyright © 2012 The Chromium Authors")]

-[assembly: AssemblyTrademark("")]

-[assembly: AssemblyCulture("")]

-

-// Setting ComVisible to false makes the types in this assembly not visible

-// to COM components.  If you need to access a type in this assembly from

-// COM, set the ComVisible attribute to true on that type.

-[assembly: ComVisible(false)]

-

-// The following GUID is for the ID of the typelib if this project is exposed to COM.

-[assembly: Guid("01a004dc-ebdc-47db-91cf-ba8ec4480c48")]

-

-// Version information for an assembly consists of the following four values:

-//

-//    Major Version

-//    Minor Version

-//    Build Number

-//    Revision

-//

-// You can specify all the values or you can default the Build and Revision Numbers

-// by using the '*' as shown below:

-[assembly: AssemblyVersion("1.0.0.0")]

-[assembly: AssemblyFileVersion("1.0.0.0")]

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("UnitTests")]
+[assembly: AssemblyDescription("Unit tests for the Native Client Visual Studio Add-in")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Google Inc.")]
+[assembly: AssemblyProduct("UnitTests")]
+[assembly: AssemblyCopyright("Copyright © 2012 The Chromium Authors")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM.
+[assembly: Guid("01a004dc-ebdc-47db-91cf-ba8ec4480c48")]
+
+// Version information for an assembly consists of the following four values:
+//
+//    Major Version
+//    Minor Version
+//    Build Number
+//    Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/UnitTests/PropertyManagerTest.cs b/UnitTests/PropertyManagerTest.cs
index 05b1297..4c701ad 100644
--- a/UnitTests/PropertyManagerTest.cs
+++ b/UnitTests/PropertyManagerTest.cs
@@ -1,237 +1,237 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace UnitTests

-{

-  using System;

-  using System.IO;

-

-  using EnvDTE;

-  using EnvDTE80;

-  using Microsoft.VisualStudio.TestTools.UnitTesting;

-

-  using NativeClientVSAddIn;

-

-  /// <summary>

-  /// This is a test class for PropertyManagerTest and is intended

-  /// to contain all PropertyManager Unit Tests

-  /// </summary>

-  [TestClass]

-  public class PropertyManagerTest

-  {

-    /// <summary>

-    /// This holds the path to the NaCl solution used in these tests.

-    /// The NaCl solution is a valid nacl/pepper plug-in VS solution.

-    /// It is copied into the testing deployment directory and opened in some tests.

-    /// Because unit-tests run in any order, the solution should not be written to

-    /// in any tests.

-    /// </summary>

-    private static string naclSolution;

-

-    /// <summary>

-    /// The main visual studio object.

-    /// </summary>

-    private DTE2 dte_;

-

-    /// <summary>

-    /// Gets or sets the test context which provides information about,

-    /// and functionality for the current test run.

-    /// </summary>

-    public TestContext TestContext { get; set; }

-

-    /// <summary>

-    /// This is run one time before any test methods are called. Here we set-up a test-copy of a

-    /// new NaCl solution for use in the tests.

-    /// </summary>

-    /// <param name="testContext">Holds information about the current test run</param>

-    [ClassInitialize]

-    public static void ClassSetup(TestContext testContext)

-    {

-      DTE2 dte = TestUtilities.StartVisualStudioInstance();

-      try

-      {

-        naclSolution = TestUtilities.CreateBlankValidNaClSolution(

-          dte,

-          "PropertyManagerTest",

-          NativeClientVSAddIn.Strings.PepperPlatformName,

-          NativeClientVSAddIn.Strings.NaClPlatformName,

-          testContext);

-      }

-      finally

-      {

-        TestUtilities.CleanUpVisualStudioInstance(dte);

-      }

-    }

-

-    /// <summary>

-    /// This is run before each test to create test resources.

-    /// </summary>

-    [TestInitialize]

-    public void TestSetup()

-    {

-      dte_ = TestUtilities.StartVisualStudioInstance();

-      try

-      {

-        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);

-      }

-      catch

-      {

-        TestUtilities.CleanUpVisualStudioInstance(dte_);

-        throw;

-      }

-    }

-

-    /// <summary>

-    /// This is run after each test to clean up things created in TestSetup().

-    /// </summary>

-    [TestCleanup]

-    public void TestCleanup()

-    {

-      TestUtilities.CleanUpVisualStudioInstance(dte_);

-    }

-

-    /// <summary>

-    /// Tests SetTarget() and SetTargetToActive().

-    /// </summary>

-    [TestMethod]

-    public void SetTargetTest()

-    {

-      string expectedSDKRootDir =

-          Environment.GetEnvironmentVariable(Strings.SDKPathEnvironmentVariable);

-      Assert.IsNotNull(expectedSDKRootDir, "SDK Path environment variable not set!");

-

-      PropertyManager target = new PropertyManager();

-      dte_.Solution.Open(naclSolution);

-

-      Project naclProject = dte_.Solution.Projects.Item(TestUtilities.BlankNaClProjectUniqueName);

-      Project notNacl = dte_.Solution.Projects.Item(TestUtilities.NotNaClProjectUniqueName);

-

-      // Invalid project.

-      target.SetTarget(notNacl, Strings.PepperPlatformName, "Debug");

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.Other,

-          target.ProjectPlatform,

-          "SetTarget should not succeed with non-nacl/pepper project.");

-

-      // Try valid project with different platforms.

-      target.SetTarget(naclProject, Strings.NaClPlatformName, "Debug");

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.NaCl,

-          target.ProjectPlatform,

-          "SetTarget did not succeed with nacl platform on valid project.");

-      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root incorrect.");

-      

-      target.SetTarget(naclProject, "Win32", "Debug");

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.Other,

-          target.ProjectPlatform,

-          "SetTarget did not set 'other' platform on when Win32 platform of valid project.");

-

-      target.SetTarget(naclProject, Strings.PepperPlatformName, "Debug");

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.Pepper,

-          target.ProjectPlatform,

-          "SetTarget did not succeed with pepper platform on valid project.");

-      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root incorrect.");

-

-      // Setting the start-up project to a non-cpp project should make loading fail.

-      object[] badStartupProj = { TestUtilities.NotNaClProjectUniqueName };

-      dte_.Solution.SolutionBuild.StartupProjects = badStartupProj;

-      target.SetTargetToActive(dte_);

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.Other,

-          target.ProjectPlatform,

-          "SetTargetToActive should not succeed with non-nacl/pepper project.");

-

-      // Setting the start-up project to correct C++ project, but also setting the platform

-      // to non-nacl/pepper should make loading fail.

-      object[] startupProj = { TestUtilities.BlankNaClProjectUniqueName };

-      dte_.Solution.SolutionBuild.StartupProjects = startupProj;

-      TestUtilities.SetSolutionConfiguration(

-          dte_, TestUtilities.BlankNaClProjectUniqueName, "Debug", "Win32");

-      target.SetTargetToActive(dte_);

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.Other,

-          target.ProjectPlatform,

-          "SetTargetToActive should not succeed with Win32 platform.");

-

-      // Now setting the platform to NaCl should make this succeed.

-      TestUtilities.SetSolutionConfiguration(

-          dte_, TestUtilities.BlankNaClProjectUniqueName, "Debug", Strings.NaClPlatformName);

-      target.SetTargetToActive(dte_);

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.NaCl,

-          target.ProjectPlatform,

-          "SetTargetToActive should succeed with NaCl platform and valid project.");

-      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root incorrect.");

-    }

-

-    /// <summary>

-    /// A test for GetProperty. Checks some non-trivial C# properties and the GetProperty method.

-    /// </summary>

-    [TestMethod]

-    public void GetPropertyTest()

-    {

-      string expectedSDKRootDir =

-          Environment.GetEnvironmentVariable(Strings.SDKPathEnvironmentVariable);

-      Assert.IsNotNull(expectedSDKRootDir, "SDK Path environment variable not set!");

-

-      // Set up the property manager to read the NaCl platform settings from BlankValidSolution.

-      PropertyManager target = new PropertyManager();

-      dte_.Solution.Open(naclSolution);

-      Project naclProject = dte_.Solution.Projects.Item(TestUtilities.BlankNaClProjectUniqueName);

-      target.SetTarget(naclProject, Strings.NaClPlatformName, "Debug");

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.NaCl,

-          target.ProjectPlatform,

-          "SetTarget did not succeed with nacl platform on valid project.");

-

-      string projectDir = Path.Combine(

-          Path.GetDirectoryName(naclSolution),

-          Path.GetDirectoryName(TestUtilities.BlankNaClProjectUniqueName)) + @"\";

-      string outputDir = Path.Combine(projectDir, "newlib") + @"\";

-      string assembly = Path.Combine(outputDir, TestUtilities.BlankNaClProjectName + ".nexe");

-

-      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root.");

-      Assert.AreEqual(projectDir, target.ProjectDirectory, "ProjectDirectory.");

-      Assert.AreEqual(outputDir, target.OutputDirectory, "OutputDirectory.");

-      Assert.AreEqual(assembly, target.PluginAssembly, "PluginAssembly.");

-      Assert.AreEqual(

-          @"newlib",

-          target.GetProperty("ConfigurationGeneral", "ToolchainName"),

-          "GetProperty() with ToolchainName incorrect.");

-    }

-

-    /// <summary>

-    /// A test for SetProperty.

-    /// </summary>

-    [TestMethod]

-    public void SetPropertyTest()

-    {

-      string setTargetSolution = TestUtilities.CreateBlankValidNaClSolution(

-          dte_,

-          "PropertyManagerTestSetTarget",

-          NativeClientVSAddIn.Strings.NaClPlatformName,

-          NativeClientVSAddIn.Strings.NaClPlatformName,

-          TestContext);

-

-      // Set up the property manager to read the NaCl platform settings from BlankValidSolution.

-      PropertyManager target = new PropertyManager();

-      dte_.Solution.Open(setTargetSolution);

-      Project naclProject = dte_.Solution.Projects.Item(TestUtilities.BlankNaClProjectUniqueName);

-      target.SetTarget(naclProject, Strings.NaClPlatformName, "Debug");

-      Assert.AreEqual(

-          PropertyManager.ProjectPlatformType.NaCl,

-          target.ProjectPlatform,

-          "SetTarget did not succeed with nacl platform on valid project.");

-

-      string newValue = "ThisIsNew";

-      target.SetProperty("ConfigurationGeneral", "VSNaClSDKRoot", newValue);

-      Assert.AreEqual(

-          newValue,

-          target.GetProperty("ConfigurationGeneral", "VSNaClSDKRoot"),

-          "SetProperty() did not set property VSNaClSDKRoot.");

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace UnitTests
+{
+  using System;
+  using System.IO;
+
+  using EnvDTE;
+  using EnvDTE80;
+  using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+  using NativeClientVSAddIn;
+
+  /// <summary>
+  /// This is a test class for PropertyManagerTest and is intended
+  /// to contain all PropertyManager Unit Tests
+  /// </summary>
+  [TestClass]
+  public class PropertyManagerTest
+  {
+    /// <summary>
+    /// This holds the path to the NaCl solution used in these tests.
+    /// The NaCl solution is a valid nacl/pepper plug-in VS solution.
+    /// It is copied into the testing deployment directory and opened in some tests.
+    /// Because unit-tests run in any order, the solution should not be written to
+    /// in any tests.
+    /// </summary>
+    private static string naclSolution;
+
+    /// <summary>
+    /// The main visual studio object.
+    /// </summary>
+    private DTE2 dte_;
+
+    /// <summary>
+    /// Gets or sets the test context which provides information about,
+    /// and functionality for the current test run.
+    /// </summary>
+    public TestContext TestContext { get; set; }
+
+    /// <summary>
+    /// This is run one time before any test methods are called. Here we set-up a test-copy of a
+    /// new NaCl solution for use in the tests.
+    /// </summary>
+    /// <param name="testContext">Holds information about the current test run</param>
+    [ClassInitialize]
+    public static void ClassSetup(TestContext testContext)
+    {
+      DTE2 dte = TestUtilities.StartVisualStudioInstance();
+      try
+      {
+        naclSolution = TestUtilities.CreateBlankValidNaClSolution(
+          dte,
+          "PropertyManagerTest",
+          NativeClientVSAddIn.Strings.PepperPlatformName,
+          NativeClientVSAddIn.Strings.NaClPlatformName,
+          testContext);
+      }
+      finally
+      {
+        TestUtilities.CleanUpVisualStudioInstance(dte);
+      }
+    }
+
+    /// <summary>
+    /// This is run before each test to create test resources.
+    /// </summary>
+    [TestInitialize]
+    public void TestSetup()
+    {
+      dte_ = TestUtilities.StartVisualStudioInstance();
+      try
+      {
+        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);
+      }
+      catch
+      {
+        TestUtilities.CleanUpVisualStudioInstance(dte_);
+        throw;
+      }
+    }
+
+    /// <summary>
+    /// This is run after each test to clean up things created in TestSetup().
+    /// </summary>
+    [TestCleanup]
+    public void TestCleanup()
+    {
+      TestUtilities.CleanUpVisualStudioInstance(dte_);
+    }
+
+    /// <summary>
+    /// Tests SetTarget() and SetTargetToActive().
+    /// </summary>
+    [TestMethod]
+    public void SetTargetTest()
+    {
+      string expectedSDKRootDir =
+          Environment.GetEnvironmentVariable(Strings.SDKPathEnvironmentVariable);
+      Assert.IsNotNull(expectedSDKRootDir, "SDK Path environment variable not set!");
+
+      PropertyManager target = new PropertyManager();
+      dte_.Solution.Open(naclSolution);
+
+      Project naclProject = dte_.Solution.Projects.Item(TestUtilities.BlankNaClProjectUniqueName);
+      Project notNacl = dte_.Solution.Projects.Item(TestUtilities.NotNaClProjectUniqueName);
+
+      // Invalid project.
+      target.SetTarget(notNacl, Strings.PepperPlatformName, "Debug");
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.Other,
+          target.ProjectPlatform,
+          "SetTarget should not succeed with non-nacl/pepper project.");
+
+      // Try valid project with different platforms.
+      target.SetTarget(naclProject, Strings.NaClPlatformName, "Debug");
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.NaCl,
+          target.ProjectPlatform,
+          "SetTarget did not succeed with nacl platform on valid project.");
+      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root incorrect.");
+      
+      target.SetTarget(naclProject, "Win32", "Debug");
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.Other,
+          target.ProjectPlatform,
+          "SetTarget did not set 'other' platform on when Win32 platform of valid project.");
+
+      target.SetTarget(naclProject, Strings.PepperPlatformName, "Debug");
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.Pepper,
+          target.ProjectPlatform,
+          "SetTarget did not succeed with pepper platform on valid project.");
+      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root incorrect.");
+
+      // Setting the start-up project to a non-cpp project should make loading fail.
+      object[] badStartupProj = { TestUtilities.NotNaClProjectUniqueName };
+      dte_.Solution.SolutionBuild.StartupProjects = badStartupProj;
+      target.SetTargetToActive(dte_);
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.Other,
+          target.ProjectPlatform,
+          "SetTargetToActive should not succeed with non-nacl/pepper project.");
+
+      // Setting the start-up project to correct C++ project, but also setting the platform
+      // to non-nacl/pepper should make loading fail.
+      object[] startupProj = { TestUtilities.BlankNaClProjectUniqueName };
+      dte_.Solution.SolutionBuild.StartupProjects = startupProj;
+      TestUtilities.SetSolutionConfiguration(
+          dte_, TestUtilities.BlankNaClProjectUniqueName, "Debug", "Win32");
+      target.SetTargetToActive(dte_);
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.Other,
+          target.ProjectPlatform,
+          "SetTargetToActive should not succeed with Win32 platform.");
+
+      // Now setting the platform to NaCl should make this succeed.
+      TestUtilities.SetSolutionConfiguration(
+          dte_, TestUtilities.BlankNaClProjectUniqueName, "Debug", Strings.NaClPlatformName);
+      target.SetTargetToActive(dte_);
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.NaCl,
+          target.ProjectPlatform,
+          "SetTargetToActive should succeed with NaCl platform and valid project.");
+      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root incorrect.");
+    }
+
+    /// <summary>
+    /// A test for GetProperty. Checks some non-trivial C# properties and the GetProperty method.
+    /// </summary>
+    [TestMethod]
+    public void GetPropertyTest()
+    {
+      string expectedSDKRootDir =
+          Environment.GetEnvironmentVariable(Strings.SDKPathEnvironmentVariable);
+      Assert.IsNotNull(expectedSDKRootDir, "SDK Path environment variable not set!");
+
+      // Set up the property manager to read the NaCl platform settings from BlankValidSolution.
+      PropertyManager target = new PropertyManager();
+      dte_.Solution.Open(naclSolution);
+      Project naclProject = dte_.Solution.Projects.Item(TestUtilities.BlankNaClProjectUniqueName);
+      target.SetTarget(naclProject, Strings.NaClPlatformName, "Debug");
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.NaCl,
+          target.ProjectPlatform,
+          "SetTarget did not succeed with nacl platform on valid project.");
+
+      string projectDir = Path.Combine(
+          Path.GetDirectoryName(naclSolution),
+          Path.GetDirectoryName(TestUtilities.BlankNaClProjectUniqueName)) + @"\";
+      string outputDir = Path.Combine(projectDir, "newlib") + @"\";
+      string assembly = Path.Combine(outputDir, TestUtilities.BlankNaClProjectName + ".nexe");
+
+      Assert.AreEqual(expectedSDKRootDir, target.SDKRootDirectory, "SDK Root.");
+      Assert.AreEqual(projectDir, target.ProjectDirectory, "ProjectDirectory.");
+      Assert.AreEqual(outputDir, target.OutputDirectory, "OutputDirectory.");
+      Assert.AreEqual(assembly, target.PluginAssembly, "PluginAssembly.");
+      Assert.AreEqual(
+          @"newlib",
+          target.GetProperty("ConfigurationGeneral", "ToolchainName"),
+          "GetProperty() with ToolchainName incorrect.");
+    }
+
+    /// <summary>
+    /// A test for SetProperty.
+    /// </summary>
+    [TestMethod]
+    public void SetPropertyTest()
+    {
+      string setTargetSolution = TestUtilities.CreateBlankValidNaClSolution(
+          dte_,
+          "PropertyManagerTestSetTarget",
+          NativeClientVSAddIn.Strings.NaClPlatformName,
+          NativeClientVSAddIn.Strings.NaClPlatformName,
+          TestContext);
+
+      // Set up the property manager to read the NaCl platform settings from BlankValidSolution.
+      PropertyManager target = new PropertyManager();
+      dte_.Solution.Open(setTargetSolution);
+      Project naclProject = dte_.Solution.Projects.Item(TestUtilities.BlankNaClProjectUniqueName);
+      target.SetTarget(naclProject, Strings.NaClPlatformName, "Debug");
+      Assert.AreEqual(
+          PropertyManager.ProjectPlatformType.NaCl,
+          target.ProjectPlatform,
+          "SetTarget did not succeed with nacl platform on valid project.");
+
+      string newValue = "ThisIsNew";
+      target.SetProperty("ConfigurationGeneral", "VSNaClSDKRoot", newValue);
+      Assert.AreEqual(
+          newValue,
+          target.GetProperty("ConfigurationGeneral", "VSNaClSDKRoot"),
+          "SetProperty() did not set property VSNaClSDKRoot.");
+    }
+  }
+}
diff --git a/UnitTests/TestUtilities.cs b/UnitTests/TestUtilities.cs
index 788a7a0..20a78dd 100644
--- a/UnitTests/TestUtilities.cs
+++ b/UnitTests/TestUtilities.cs
@@ -1,463 +1,463 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace UnitTests

-{

-  using System;

-  using System.Collections.Generic;

-  using System.IO;

-  using System.Linq;

-  using System.Management;

-

-  using EnvDTE;

-  using EnvDTE80;

-  using Microsoft.VisualStudio.TestTools.UnitTesting;

-  using Microsoft.VisualStudio.VCProjectEngine;

-

-  /// <summary>

-  /// This class contains utilities for running tests.

-  /// </summary>

-  public static class TestUtilities

-  {

-    /// <summary>

-    /// Name of the NaCl project in BlankValidSolution.

-    /// </summary>

-    public const string BlankNaClProjectName = @"NaClProject";

-

-    /// <summary>

-    /// Uniquename of the NaCl project in BlankValidSolution.

-    /// </summary>

-    public const string BlankNaClProjectUniqueName = @"NaClProject\NaClProject.vcxproj";

-

-    /// <summary>

-    /// Uniquename of the non-NaCl project in BlankValidSolution.

-    /// </summary>

-    public const string NotNaClProjectUniqueName = @"NotNaCl\NotNaCl.csproj";

-

-    /// <summary>

-    /// A generic boolean statement to be used with RetryWithTimeout.

-    /// </summary>

-    /// <returns>True if the statement is true, false if false.</returns>

-    public delegate bool RetryStatement();

-

-    /// <summary>

-    /// This starts an instance of Visual Studio and get its DTE object.

-    /// </summary>

-    /// <returns>DTE of the started instance.</returns>

-    public static DTE2 StartVisualStudioInstance()

-    {

-      // Set up filter to handle threading events and automatically retry calls

-      // to dte which fail because dte is busy.

-      ComMessageFilter.Register();

-

-      Type visualStudioType = Type.GetTypeFromProgID("VisualStudio.DTE.10.0");

-      DTE2 visualStudio = Activator.CreateInstance(visualStudioType) as DTE2;

-      if (visualStudio == null)

-      {

-        throw new Exception("Visual Studio failed to start");

-      }

-

-      visualStudio.MainWindow.Visible = true;

-      return visualStudio;

-    }

-

-    /// <summary>

-    /// This properly cleans up after StartVisualStudioInstance().

-    /// </summary>

-    /// <param name="dte">Dte instance returned by StartVisualStudioInstance().</param>

-    public static void CleanUpVisualStudioInstance(DTE2 dte)

-    {

-      if (dte != null)

-      {

-        if (dte.Solution != null)

-        {

-          dte.Solution.Close();

-        }

-

-        dte.Quit();

-      }

-

-      // Stop the message filter.

-      ComMessageFilter.Revoke();

-    }

-

-    /// <summary>

-    /// Creates a blank valid NaCl project with up-to-date settings.  The path to the new solution

-    /// is returned.

-    /// </summary>

-    /// <param name="dte">Interface to an open Visual Studio instance to use.</param>

-    /// <param name="name">Name to give newly created solution.</param>

-    /// <param name="pepperCopyFrom">Platform name to copy existing settings from to pepper.</param>

-    /// <param name="naclCopyFrom">Platform name to copy existing settings from to NaCl.</param>

-    /// <param name="testContext">Test context used for finding deployment directory.</param>

-    /// <returns>Path to the newly created solution.</returns>

-    public static string CreateBlankValidNaClSolution(

-        DTE2 dte, string name, string pepperCopyFrom, string naclCopyFrom, TestContext testContext)

-    {

-      const string BlankSolution = "BlankValidSolution";

-      string newSolutionDir = Path.Combine(testContext.DeploymentDirectory, name);

-      string newSolution = Path.Combine(newSolutionDir, BlankSolution + ".sln");

-      CopyDirectory(Path.Combine(testContext.DeploymentDirectory, BlankSolution), newSolutionDir);

-

-      try

-      {

-        dte.Solution.Open(newSolution);

-        Project proj = dte.Solution.Projects.Item(BlankNaClProjectUniqueName);

-

-        // Order matters if copying from the other Native Client type.

-        if (pepperCopyFrom.Equals(NativeClientVSAddIn.Strings.NaClPlatformName))

-        {

-          proj.ConfigurationManager.AddPlatform(

-            NativeClientVSAddIn.Strings.NaClPlatformName, naclCopyFrom, true);

-          proj.ConfigurationManager.AddPlatform(

-            NativeClientVSAddIn.Strings.PepperPlatformName, pepperCopyFrom, true);

-        }

-        else

-        {

-          proj.ConfigurationManager.AddPlatform(

-            NativeClientVSAddIn.Strings.PepperPlatformName, pepperCopyFrom, true);

-          proj.ConfigurationManager.AddPlatform(

-            NativeClientVSAddIn.Strings.NaClPlatformName, naclCopyFrom, true);

-        }

-

-        // Set the active solution configuration to Debug|NaCl.

-        SetSolutionConfiguration(

-            dte, BlankNaClProjectUniqueName, "Debug", NativeClientVSAddIn.Strings.NaClPlatformName);

-

-        proj.Save();

-        dte.Solution.SaveAs(newSolution);

-      }

-      finally

-      {

-        if (dte.Solution != null)

-        {

-          dte.Solution.Close();

-        }

-      }

-

-      return newSolution;

-    }

-

-    /// <summary>

-    /// This returns the text contained in the given output window pane.

-    /// </summary>

-    /// <param name="pane">Pane to get text from.</param>

-    /// <returns>Text in the window.</returns>

-    public static string GetPaneText(OutputWindowPane pane)

-    {

-      TextSelection selection = pane.TextDocument.Selection;

-      selection.StartOfDocument(false);

-      selection.EndOfDocument(true);

-      return selection.Text;

-    }

-

-    /// <summary>

-    /// This starts a python process that just sleeps waiting to be killed.

-    /// It can be used with DoesProcessExist() to verify that a process started/exited.

-    /// </summary>

-    /// <param name="identifierString">

-    /// A unique string to identify the process via its command line arguments.

-    /// </param>

-    /// <param name="timeout">Time in seconds to wait before process exits on its own.</param>

-    /// <returns>The process object that was started.</returns>

-    public static System.Diagnostics.Process StartProcessForKilling(

-        string identifierString, int timeout)

-    {

-      string args = string.Format(

-          "-c \"import time; time.sleep({0}); print '{1}'\"",

-          timeout,

-          identifierString);

-      System.Diagnostics.Process proc = new System.Diagnostics.Process();

-      proc.StartInfo.CreateNoWindow = true;

-      proc.StartInfo.UseShellExecute = false;

-      proc.StartInfo.FileName = "python.exe";

-      proc.StartInfo.Arguments = args;

-      proc.Start();

-      return proc;

-    }

-

-    /// <summary>

-    /// This returns true if there is a running process that has command line arguments

-    /// containing the given Strings.  The search is case-insensitive.

-    /// </summary>

-    /// <param name="processName">Name of the process executable.</param>

-    /// <param name="commandLineIdentifiers">Strings to check for.</param>

-    /// <returns>True if some process has the Strings in its command line arguments.</returns>

-    public static bool DoesProcessExist(string processName, params string[] commandLineIdentifiers)

-    {

-      List<string> results = new List<string>();

-      string query =

-          string.Format("select CommandLine from Win32_Process where Name='{0}'", processName);

-      using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))

-      {

-        using (ManagementObjectCollection result = searcher.Get())

-        {

-          foreach (ManagementObject process in result)

-          {

-            string commandLine = process["CommandLine"] as string;

-            if (string.IsNullOrEmpty(commandLine))

-            {

-              break;

-            }

-

-            // Check if the command line contains each of the required identifiers.

-            if (commandLineIdentifiers.All(i => commandLine.Contains(i)))

-            {

-              return true;

-            }

-          }

-        }

-      }

-

-      return false;

-    }

-

-    /// <summary>

-    /// Sets the active configuration for the solution by specifying the configuration name

-    /// and platform name. A solution configuration containing a project configuration that has

-    /// the config and platform names specified for the specified project is selected.

-    /// </summary>

-    /// <param name="dte">The main visual studio object.</param>

-    /// <param name="projectUniqueName">UniqueName of the project to match.</param>

-    /// <param name="configurationName">Ex: "Debug" or "Release".</param>

-    /// <param name="platformName">Ex: "Win32" or "NaCl" or "PPAPI".</param>

-    public static void SetSolutionConfiguration(

-        DTE2 dte,

-        string projectUniqueName,

-        string configurationName,

-        string platformName)

-    {

-      foreach (EnvDTE.SolutionConfiguration config in

-          dte.Solution.SolutionBuild.SolutionConfigurations)

-      {

-        EnvDTE.SolutionContext context = null;

-        try

-        {

-          context = config.SolutionContexts.Item(projectUniqueName);

-        }

-        catch (ArgumentException)

-        {

-          throw new Exception(

-              string.Format("Project unique name not found in solution: {0}", projectUniqueName));

-        }

-

-        if (context == null)

-        {

-          throw new Exception("Failed to get solution context");

-        }

-

-        if (context.PlatformName == platformName && context.ConfigurationName == configurationName)

-        {

-          config.Activate();

-          return;

-        }

-      }

-

-      throw new Exception(string.Format(

-          "Matching configuration not found for {0}: {1}|{2}",

-          projectUniqueName,

-          platformName,

-          configurationName));

-    }

-

-    /// <summary>

-    /// Returns a VCConfiguration object with a matching configuration name and platform type.

-    /// </summary>

-    /// <param name="project">Project to get the configuration from.</param>

-    /// <param name="name">Name of configuration (e.g. 'Debug').</param>

-    /// <param name="platform">Name of the platform (e.g. 'NaCl').</param>

-    /// <returns>A matching VCConfiguration object.</returns>

-    public static VCConfiguration GetVCConfiguration(Project project, string name, string platform)

-    {

-      VCProject vcproj = (VCProject)project.Object;

-      IVCCollection configs = vcproj.Configurations;

-

-      foreach (VCConfiguration config in configs)

-      {

-        if (config.ConfigurationName == name && config.Platform.Name == platform)

-        {

-          return config;

-        }

-      }

-

-      throw new Exception(

-          string.Format("Project does not have configuration: {0}|{1}", platform, name));

-    }

-

-    /// <summary>

-    /// Tests that a given property has a specific value in a certain VCConfiguration

-    /// </summary>

-    /// <param name="configuration">Gives the platform and configuration type</param>

-    /// <param name="pageName">Property page name where property resides.</param>

-    /// <param name="propertyName">Name of the property to check.</param>

-    /// <param name="expectedValue">Expected value of the property.</param>

-    /// <param name="ignoreCase">Ignore case when comparing the expected and actual values.</param>

-    public static void AssertPropertyEquals(

-        VCConfiguration configuration,

-        string pageName,

-        string propertyName,

-        string expectedValue,

-        bool ignoreCase)

-    {

-      IVCRulePropertyStorage rule = configuration.Rules.Item(pageName);

-      string callInfo = string.Format(

-          "Page: {0}, Property: {1}, Configuration: {2}",

-          pageName,

-          propertyName,

-          configuration.ConfigurationName);

-

-      Assert.AreEqual(

-          expectedValue,

-          rule.GetUnevaluatedPropertyValue(propertyName),

-          ignoreCase,

-          callInfo);

-    }

-

-    /// <summary>

-    /// Tests that a given property contains a specific string in a certain VCConfiguration

-    /// </summary>

-    /// <param name="configuration">Gives the platform and configuration type</param>

-    /// <param name="pageName">Property page name where property resides.</param>

-    /// <param name="propertyName">Name of the property to check.</param>

-    /// <param name="expectedValue">Expected string to contain.</param>

-    /// <param name="ignoreCase">Ignore case when comparing the expected and actual values.</param>

-    public static void AssertPropertyContains(

-        VCConfiguration configuration,

-        string pageName,

-        string propertyName,

-        string expectedValue,

-        bool ignoreCase)

-    {

-      StringComparison caseSensitive = ignoreCase ?

-          StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

-

-      IVCRulePropertyStorage rule = configuration.Rules.Item(pageName);

-      string propertyValue = rule.GetUnevaluatedPropertyValue(propertyName);

-

-      string message = string.Format(

-          "{0} should be contained in {1}. Page: {2}, Property: {3}, Configuration: {4}",

-          expectedValue,

-          propertyValue,

-          pageName,

-          propertyName,

-          configuration.ConfigurationName);

-

-      Assert.IsTrue(propertyValue.Contains(expectedValue, caseSensitive), message);

-    }

-

-    /// <summary>

-    /// Tests that a given property is not null or empty.

-    /// </summary>

-    /// <param name="configuration">Gives the platform and configuration type</param>

-    /// <param name="pageName">Property page name where property resides.</param>

-    /// <param name="propertyName">Name of the property to check.</param>

-    public static void AssertPropertyIsNotNullOrEmpty(

-        VCConfiguration configuration,

-        string pageName,

-        string propertyName)

-    {

-      IVCRulePropertyStorage rule = configuration.Rules.Item(pageName);

-      string propertyValue = rule.GetUnevaluatedPropertyValue(propertyName);

-

-      string message = string.Format(

-          "{0} was null or empty. Page: {1}, Configuration: {2}",

-          propertyName,

-          pageName,

-          configuration.ConfigurationName);

-

-      Assert.IsFalse(string.IsNullOrEmpty(propertyValue), message);

-    }

-

-    /// <summary>

-    /// Ensures that the add-in is configured to load on start. If it isn't then some tests may

-    /// unexpectedly fail, this check helps catch that problem early.

-    /// </summary>

-    /// <param name="dte">The main Visual Studio interface.</param>

-    /// <param name="addInName">The name of the add-in to check if loaded.</param>

-    public static void AssertAddinLoaded(DTE2 dte, string addInName)

-    {

-      bool found = false;

-      foreach (AddIn addin in dte.AddIns)

-      {

-        if (addin.Connected && addInName.Equals(addin.Name))

-        {

-          found = true;

-          break;

-        }

-      }

-

-      Assert.IsTrue(found, "Add-in is not configured to load on start.");

-    }

-

-    /// <summary>

-    /// Will retry the given statement up to maxRetry times while pausing between each try for

-    /// the given interval.

-    /// </summary>

-    /// <param name="test">Generic boolean statement.</param>

-    /// <param name="interval">Amount of time to wait between each retry.</param>

-    /// <param name="maxRetry">Maximum number of retries.</param>

-    /// <param name="message">Message to print on failure.</param>

-    public static void AssertTrueWithTimeout(

-        RetryStatement test, TimeSpan interval, int maxRetry, string message)

-    {

-      for (int tryCount = 0; tryCount <= maxRetry; tryCount++)

-      {

-        if (test.Invoke())

-        {

-          return;

-        }

-

-        System.Threading.Thread.Sleep(interval);

-      }

-

-      throw new Exception(string.Format("Statement timed out. {0}", message));

-    }

-

-    /// <summary>

-    /// Extends the string class to allow checking if a string contains another string

-    /// allowing a comparison type (such as case-insensitivity).

-    /// </summary>

-    /// <param name="source">Base string to search.</param>

-    /// <param name="toCheck">String to check if contained within base string.</param>

-    /// <param name="comparison">Comparison type.</param>

-    /// <returns>True if toCheck is contained in source.</returns>

-    public static bool Contains(this string source, string toCheck, StringComparison comparison)

-    {

-      return source.IndexOf(toCheck, comparison) != -1;

-    }

-

-    /// <summary>

-    /// Copies the entire contents of a directory and sub directories.

-    /// </summary>

-    /// <param name="source">Directory to copy from.</param>

-    /// <param name="dest">Directory to copy to.</param>

-    public static void CopyDirectory(string source, string dest)

-    {

-      DirectoryInfo dir = new DirectoryInfo(source);

-

-      if (!dir.Exists)

-      {

-        throw new DirectoryNotFoundException(source);

-      }

-

-      if (!Directory.Exists(dest))

-      {

-        Directory.CreateDirectory(dest);

-      }

-

-      FileInfo[] files = dir.GetFiles();

-      foreach (FileInfo file in files)

-      {

-        string path = Path.Combine(dest, file.Name);

-        file.CopyTo(path, false);

-      }

-

-      foreach (DirectoryInfo subdir in dir.GetDirectories())

-      {

-        string path = Path.Combine(dest, subdir.Name);

-        CopyDirectory(subdir.FullName, path);

-      }

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace UnitTests
+{
+  using System;
+  using System.Collections.Generic;
+  using System.IO;
+  using System.Linq;
+  using System.Management;
+
+  using EnvDTE;
+  using EnvDTE80;
+  using Microsoft.VisualStudio.TestTools.UnitTesting;
+  using Microsoft.VisualStudio.VCProjectEngine;
+
+  /// <summary>
+  /// This class contains utilities for running tests.
+  /// </summary>
+  public static class TestUtilities
+  {
+    /// <summary>
+    /// Name of the NaCl project in BlankValidSolution.
+    /// </summary>
+    public const string BlankNaClProjectName = @"NaClProject";
+
+    /// <summary>
+    /// Uniquename of the NaCl project in BlankValidSolution.
+    /// </summary>
+    public const string BlankNaClProjectUniqueName = @"NaClProject\NaClProject.vcxproj";
+
+    /// <summary>
+    /// Uniquename of the non-NaCl project in BlankValidSolution.
+    /// </summary>
+    public const string NotNaClProjectUniqueName = @"NotNaCl\NotNaCl.csproj";
+
+    /// <summary>
+    /// A generic boolean statement to be used with RetryWithTimeout.
+    /// </summary>
+    /// <returns>True if the statement is true, false if false.</returns>
+    public delegate bool RetryStatement();
+
+    /// <summary>
+    /// This starts an instance of Visual Studio and get its DTE object.
+    /// </summary>
+    /// <returns>DTE of the started instance.</returns>
+    public static DTE2 StartVisualStudioInstance()
+    {
+      // Set up filter to handle threading events and automatically retry calls
+      // to dte which fail because dte is busy.
+      ComMessageFilter.Register();
+
+      Type visualStudioType = Type.GetTypeFromProgID("VisualStudio.DTE.10.0");
+      DTE2 visualStudio = Activator.CreateInstance(visualStudioType) as DTE2;
+      if (visualStudio == null)
+      {
+        throw new Exception("Visual Studio failed to start");
+      }
+
+      visualStudio.MainWindow.Visible = true;
+      return visualStudio;
+    }
+
+    /// <summary>
+    /// This properly cleans up after StartVisualStudioInstance().
+    /// </summary>
+    /// <param name="dte">Dte instance returned by StartVisualStudioInstance().</param>
+    public static void CleanUpVisualStudioInstance(DTE2 dte)
+    {
+      if (dte != null)
+      {
+        if (dte.Solution != null)
+        {
+          dte.Solution.Close();
+        }
+
+        dte.Quit();
+      }
+
+      // Stop the message filter.
+      ComMessageFilter.Revoke();
+    }
+
+    /// <summary>
+    /// Creates a blank valid NaCl project with up-to-date settings.  The path to the new solution
+    /// is returned.
+    /// </summary>
+    /// <param name="dte">Interface to an open Visual Studio instance to use.</param>
+    /// <param name="name">Name to give newly created solution.</param>
+    /// <param name="pepperCopyFrom">Platform name to copy existing settings from to pepper.</param>
+    /// <param name="naclCopyFrom">Platform name to copy existing settings from to NaCl.</param>
+    /// <param name="testContext">Test context used for finding deployment directory.</param>
+    /// <returns>Path to the newly created solution.</returns>
+    public static string CreateBlankValidNaClSolution(
+        DTE2 dte, string name, string pepperCopyFrom, string naclCopyFrom, TestContext testContext)
+    {
+      const string BlankSolution = "BlankValidSolution";
+      string newSolutionDir = Path.Combine(testContext.DeploymentDirectory, name);
+      string newSolution = Path.Combine(newSolutionDir, BlankSolution + ".sln");
+      CopyDirectory(Path.Combine(testContext.DeploymentDirectory, BlankSolution), newSolutionDir);
+
+      try
+      {
+        dte.Solution.Open(newSolution);
+        Project proj = dte.Solution.Projects.Item(BlankNaClProjectUniqueName);
+
+        // Order matters if copying from the other Native Client type.
+        if (pepperCopyFrom.Equals(NativeClientVSAddIn.Strings.NaClPlatformName))
+        {
+          proj.ConfigurationManager.AddPlatform(
+            NativeClientVSAddIn.Strings.NaClPlatformName, naclCopyFrom, true);
+          proj.ConfigurationManager.AddPlatform(
+            NativeClientVSAddIn.Strings.PepperPlatformName, pepperCopyFrom, true);
+        }
+        else
+        {
+          proj.ConfigurationManager.AddPlatform(
+            NativeClientVSAddIn.Strings.PepperPlatformName, pepperCopyFrom, true);
+          proj.ConfigurationManager.AddPlatform(
+            NativeClientVSAddIn.Strings.NaClPlatformName, naclCopyFrom, true);
+        }
+
+        // Set the active solution configuration to Debug|NaCl.
+        SetSolutionConfiguration(
+            dte, BlankNaClProjectUniqueName, "Debug", NativeClientVSAddIn.Strings.NaClPlatformName);
+
+        proj.Save();
+        dte.Solution.SaveAs(newSolution);
+      }
+      finally
+      {
+        if (dte.Solution != null)
+        {
+          dte.Solution.Close();
+        }
+      }
+
+      return newSolution;
+    }
+
+    /// <summary>
+    /// This returns the text contained in the given output window pane.
+    /// </summary>
+    /// <param name="pane">Pane to get text from.</param>
+    /// <returns>Text in the window.</returns>
+    public static string GetPaneText(OutputWindowPane pane)
+    {
+      TextSelection selection = pane.TextDocument.Selection;
+      selection.StartOfDocument(false);
+      selection.EndOfDocument(true);
+      return selection.Text;
+    }
+
+    /// <summary>
+    /// This starts a python process that just sleeps waiting to be killed.
+    /// It can be used with DoesProcessExist() to verify that a process started/exited.
+    /// </summary>
+    /// <param name="identifierString">
+    /// A unique string to identify the process via its command line arguments.
+    /// </param>
+    /// <param name="timeout">Time in seconds to wait before process exits on its own.</param>
+    /// <returns>The process object that was started.</returns>
+    public static System.Diagnostics.Process StartProcessForKilling(
+        string identifierString, int timeout)
+    {
+      string args = string.Format(
+          "-c \"import time; time.sleep({0}); print '{1}'\"",
+          timeout,
+          identifierString);
+      System.Diagnostics.Process proc = new System.Diagnostics.Process();
+      proc.StartInfo.CreateNoWindow = true;
+      proc.StartInfo.UseShellExecute = false;
+      proc.StartInfo.FileName = "python.exe";
+      proc.StartInfo.Arguments = args;
+      proc.Start();
+      return proc;
+    }
+
+    /// <summary>
+    /// This returns true if there is a running process that has command line arguments
+    /// containing the given Strings.  The search is case-insensitive.
+    /// </summary>
+    /// <param name="processName">Name of the process executable.</param>
+    /// <param name="commandLineIdentifiers">Strings to check for.</param>
+    /// <returns>True if some process has the Strings in its command line arguments.</returns>
+    public static bool DoesProcessExist(string processName, params string[] commandLineIdentifiers)
+    {
+      List<string> results = new List<string>();
+      string query =
+          string.Format("select CommandLine from Win32_Process where Name='{0}'", processName);
+      using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
+      {
+        using (ManagementObjectCollection result = searcher.Get())
+        {
+          foreach (ManagementObject process in result)
+          {
+            string commandLine = process["CommandLine"] as string;
+            if (string.IsNullOrEmpty(commandLine))
+            {
+              break;
+            }
+
+            // Check if the command line contains each of the required identifiers.
+            if (commandLineIdentifiers.All(i => commandLine.Contains(i)))
+            {
+              return true;
+            }
+          }
+        }
+      }
+
+      return false;
+    }
+
+    /// <summary>
+    /// Sets the active configuration for the solution by specifying the configuration name
+    /// and platform name. A solution configuration containing a project configuration that has
+    /// the config and platform names specified for the specified project is selected.
+    /// </summary>
+    /// <param name="dte">The main visual studio object.</param>
+    /// <param name="projectUniqueName">UniqueName of the project to match.</param>
+    /// <param name="configurationName">Ex: "Debug" or "Release".</param>
+    /// <param name="platformName">Ex: "Win32" or "NaCl" or "PPAPI".</param>
+    public static void SetSolutionConfiguration(
+        DTE2 dte,
+        string projectUniqueName,
+        string configurationName,
+        string platformName)
+    {
+      foreach (EnvDTE.SolutionConfiguration config in
+          dte.Solution.SolutionBuild.SolutionConfigurations)
+      {
+        EnvDTE.SolutionContext context = null;
+        try
+        {
+          context = config.SolutionContexts.Item(projectUniqueName);
+        }
+        catch (ArgumentException)
+        {
+          throw new Exception(
+              string.Format("Project unique name not found in solution: {0}", projectUniqueName));
+        }
+
+        if (context == null)
+        {
+          throw new Exception("Failed to get solution context");
+        }
+
+        if (context.PlatformName == platformName && context.ConfigurationName == configurationName)
+        {
+          config.Activate();
+          return;
+        }
+      }
+
+      throw new Exception(string.Format(
+          "Matching configuration not found for {0}: {1}|{2}",
+          projectUniqueName,
+          platformName,
+          configurationName));
+    }
+
+    /// <summary>
+    /// Returns a VCConfiguration object with a matching configuration name and platform type.
+    /// </summary>
+    /// <param name="project">Project to get the configuration from.</param>
+    /// <param name="name">Name of configuration (e.g. 'Debug').</param>
+    /// <param name="platform">Name of the platform (e.g. 'NaCl').</param>
+    /// <returns>A matching VCConfiguration object.</returns>
+    public static VCConfiguration GetVCConfiguration(Project project, string name, string platform)
+    {
+      VCProject vcproj = (VCProject)project.Object;
+      IVCCollection configs = vcproj.Configurations;
+
+      foreach (VCConfiguration config in configs)
+      {
+        if (config.ConfigurationName == name && config.Platform.Name == platform)
+        {
+          return config;
+        }
+      }
+
+      throw new Exception(
+          string.Format("Project does not have configuration: {0}|{1}", platform, name));
+    }
+
+    /// <summary>
+    /// Tests that a given property has a specific value in a certain VCConfiguration
+    /// </summary>
+    /// <param name="configuration">Gives the platform and configuration type</param>
+    /// <param name="pageName">Property page name where property resides.</param>
+    /// <param name="propertyName">Name of the property to check.</param>
+    /// <param name="expectedValue">Expected value of the property.</param>
+    /// <param name="ignoreCase">Ignore case when comparing the expected and actual values.</param>
+    public static void AssertPropertyEquals(
+        VCConfiguration configuration,
+        string pageName,
+        string propertyName,
+        string expectedValue,
+        bool ignoreCase)
+    {
+      IVCRulePropertyStorage rule = configuration.Rules.Item(pageName);
+      string callInfo = string.Format(
+          "Page: {0}, Property: {1}, Configuration: {2}",
+          pageName,
+          propertyName,
+          configuration.ConfigurationName);
+
+      Assert.AreEqual(
+          expectedValue,
+          rule.GetUnevaluatedPropertyValue(propertyName),
+          ignoreCase,
+          callInfo);
+    }
+
+    /// <summary>
+    /// Tests that a given property contains a specific string in a certain VCConfiguration
+    /// </summary>
+    /// <param name="configuration">Gives the platform and configuration type</param>
+    /// <param name="pageName">Property page name where property resides.</param>
+    /// <param name="propertyName">Name of the property to check.</param>
+    /// <param name="expectedValue">Expected string to contain.</param>
+    /// <param name="ignoreCase">Ignore case when comparing the expected and actual values.</param>
+    public static void AssertPropertyContains(
+        VCConfiguration configuration,
+        string pageName,
+        string propertyName,
+        string expectedValue,
+        bool ignoreCase)
+    {
+      StringComparison caseSensitive = ignoreCase ?
+          StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
+
+      IVCRulePropertyStorage rule = configuration.Rules.Item(pageName);
+      string propertyValue = rule.GetUnevaluatedPropertyValue(propertyName);
+
+      string message = string.Format(
+          "{0} should be contained in {1}. Page: {2}, Property: {3}, Configuration: {4}",
+          expectedValue,
+          propertyValue,
+          pageName,
+          propertyName,
+          configuration.ConfigurationName);
+
+      Assert.IsTrue(propertyValue.Contains(expectedValue, caseSensitive), message);
+    }
+
+    /// <summary>
+    /// Tests that a given property is not null or empty.
+    /// </summary>
+    /// <param name="configuration">Gives the platform and configuration type</param>
+    /// <param name="pageName">Property page name where property resides.</param>
+    /// <param name="propertyName">Name of the property to check.</param>
+    public static void AssertPropertyIsNotNullOrEmpty(
+        VCConfiguration configuration,
+        string pageName,
+        string propertyName)
+    {
+      IVCRulePropertyStorage rule = configuration.Rules.Item(pageName);
+      string propertyValue = rule.GetUnevaluatedPropertyValue(propertyName);
+
+      string message = string.Format(
+          "{0} was null or empty. Page: {1}, Configuration: {2}",
+          propertyName,
+          pageName,
+          configuration.ConfigurationName);
+
+      Assert.IsFalse(string.IsNullOrEmpty(propertyValue), message);
+    }
+
+    /// <summary>
+    /// Ensures that the add-in is configured to load on start. If it isn't then some tests may
+    /// unexpectedly fail, this check helps catch that problem early.
+    /// </summary>
+    /// <param name="dte">The main Visual Studio interface.</param>
+    /// <param name="addInName">The name of the add-in to check if loaded.</param>
+    public static void AssertAddinLoaded(DTE2 dte, string addInName)
+    {
+      bool found = false;
+      foreach (AddIn addin in dte.AddIns)
+      {
+        if (addin.Connected && addInName.Equals(addin.Name))
+        {
+          found = true;
+          break;
+        }
+      }
+
+      Assert.IsTrue(found, "Add-in is not configured to load on start.");
+    }
+
+    /// <summary>
+    /// Will retry the given statement up to maxRetry times while pausing between each try for
+    /// the given interval.
+    /// </summary>
+    /// <param name="test">Generic boolean statement.</param>
+    /// <param name="interval">Amount of time to wait between each retry.</param>
+    /// <param name="maxRetry">Maximum number of retries.</param>
+    /// <param name="message">Message to print on failure.</param>
+    public static void AssertTrueWithTimeout(
+        RetryStatement test, TimeSpan interval, int maxRetry, string message)
+    {
+      for (int tryCount = 0; tryCount <= maxRetry; tryCount++)
+      {
+        if (test.Invoke())
+        {
+          return;
+        }
+
+        System.Threading.Thread.Sleep(interval);
+      }
+
+      throw new Exception(string.Format("Statement timed out. {0}", message));
+    }
+
+    /// <summary>
+    /// Extends the string class to allow checking if a string contains another string
+    /// allowing a comparison type (such as case-insensitivity).
+    /// </summary>
+    /// <param name="source">Base string to search.</param>
+    /// <param name="toCheck">String to check if contained within base string.</param>
+    /// <param name="comparison">Comparison type.</param>
+    /// <returns>True if toCheck is contained in source.</returns>
+    public static bool Contains(this string source, string toCheck, StringComparison comparison)
+    {
+      return source.IndexOf(toCheck, comparison) != -1;
+    }
+
+    /// <summary>
+    /// Copies the entire contents of a directory and sub directories.
+    /// </summary>
+    /// <param name="source">Directory to copy from.</param>
+    /// <param name="dest">Directory to copy to.</param>
+    public static void CopyDirectory(string source, string dest)
+    {
+      DirectoryInfo dir = new DirectoryInfo(source);
+
+      if (!dir.Exists)
+      {
+        throw new DirectoryNotFoundException(source);
+      }
+
+      if (!Directory.Exists(dest))
+      {
+        Directory.CreateDirectory(dest);
+      }
+
+      FileInfo[] files = dir.GetFiles();
+      foreach (FileInfo file in files)
+      {
+        string path = Path.Combine(dest, file.Name);
+        file.CopyTo(path, false);
+      }
+
+      foreach (DirectoryInfo subdir in dir.GetDirectories())
+      {
+        string path = Path.Combine(dest, subdir.Name);
+        CopyDirectory(subdir.FullName, path);
+      }
+    }
+  }
+}
diff --git a/UnitTests/WebServerTest.cs b/UnitTests/WebServerTest.cs
index 08e8ef9..a4b432a 100644
--- a/UnitTests/WebServerTest.cs
+++ b/UnitTests/WebServerTest.cs
@@ -1,132 +1,132 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.

-// Use of this source code is governed by a BSD-style license that can be

-// found in the LICENSE file.

-

-namespace UnitTests

-{

-  using System;

-

-  using EnvDTE;

-  using EnvDTE80;

-  using Microsoft.VisualStudio.TestTools.UnitTesting;

-

-  using NativeClientVSAddIn;

-

-  /// <summary>

-  /// This is a test class for WebServerTest and is intended

-  /// to contain all WebServer Unit Tests

-  /// </summary>

-  [TestClass]

-  public class WebServerTest

-  {

-    /// <summary>

-    /// The main visual studio object.

-    /// </summary>

-    private DTE2 dte_;

-

-    /// <summary>

-    /// Gets or sets the test context which provides

-    /// information about and functionality for the current test run.

-    /// </summary>

-    public TestContext TestContext { get; set; }

-

-    /// <summary>

-    /// This is run before each test to create test resources.

-    /// </summary>

-    [TestInitialize]

-    public void TestSetup()

-    {

-      dte_ = TestUtilities.StartVisualStudioInstance();

-      try

-      {

-        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);

-      }

-      catch

-      {

-        TestUtilities.CleanUpVisualStudioInstance(dte_);

-        throw;

-      }

-    }

-

-    /// <summary>

-    /// This is run after each test to clean up things created in TestSetup().

-    /// </summary>

-    [TestCleanup]

-    public void TestCleanup()

-    {

-      TestUtilities.CleanUpVisualStudioInstance(dte_);

-    }

-

-    /// <summary>

-    /// A test for WebServer Constructor. Starts the web server.

-    /// </summary>

-    [TestMethod]

-    public void WebServerConstructorTest()

-    {

-      OutputWindowPane outputWindowPane = dte_.ToolWindows.OutputWindow.OutputWindowPanes.Add(

-          Strings.WebServerOutputWindowTitle);

-

-      // Set up mock property manager to return the desired property values.

-      MockPropertyManager properties = new MockPropertyManager(

-        PropertyManager.ProjectPlatformType.Pepper,

-        delegate(string page, string name)

-        {

-          switch (page)

-          {

-            case "ConfigurationGeneral":

-              switch (name)

-              {

-                case "VSNaClSDKRoot": return System.Environment.GetEnvironmentVariable(

-                    NativeClientVSAddIn.Strings.SDKPathEnvironmentVariable);

-                case "NaClWebServerPort": return "5105";

-              }

-

-              break;

-            case "Property":

-              switch (name)

-              {

-                case "ProjectDirectory": return TestContext.DeploymentDirectory;

-              }

-

-              break;

-          }

-

-          return null;

-        },

-        null);

-

-      WebServer target = null;

-      try

-      {

-        target = new WebServer(outputWindowPane, properties);

-

-        TestUtilities.AssertTrueWithTimeout(

-          () => !string.IsNullOrEmpty(TestUtilities.GetPaneText(outputWindowPane)),

-          TimeSpan.FromMilliseconds(500),

-          20,

-          "Pane text never appeared");

-

-        TestUtilities.AssertTrueWithTimeout(

-            () => TestUtilities.DoesProcessExist("python.exe", "5105", "httpd.py"),

-            TimeSpan.FromMilliseconds(500),

-            20,

-            "Web server failed to start.");

-

-        target.Dispose();

-

-        TestUtilities.AssertTrueWithTimeout(

-            () => !TestUtilities.DoesProcessExist("python.exe", "5105", "httpd.py"),

-            TimeSpan.FromMilliseconds(500),

-            20,

-            "Web server failed to shut down.");

-      }

-      finally

-      {

-        if (target != null)

-        {

-          target.Dispose();

-        }

-      }

-    }

-  }

-}

+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace UnitTests
+{
+  using System;
+
+  using EnvDTE;
+  using EnvDTE80;
+  using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+  using NativeClientVSAddIn;
+
+  /// <summary>
+  /// This is a test class for WebServerTest and is intended
+  /// to contain all WebServer Unit Tests
+  /// </summary>
+  [TestClass]
+  public class WebServerTest
+  {
+    /// <summary>
+    /// The main visual studio object.
+    /// </summary>
+    private DTE2 dte_;
+
+    /// <summary>
+    /// Gets or sets the test context which provides
+    /// information about and functionality for the current test run.
+    /// </summary>
+    public TestContext TestContext { get; set; }
+
+    /// <summary>
+    /// This is run before each test to create test resources.
+    /// </summary>
+    [TestInitialize]
+    public void TestSetup()
+    {
+      dte_ = TestUtilities.StartVisualStudioInstance();
+      try
+      {
+        TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInName);
+      }
+      catch
+      {
+        TestUtilities.CleanUpVisualStudioInstance(dte_);
+        throw;
+      }
+    }
+
+    /// <summary>
+    /// This is run after each test to clean up things created in TestSetup().
+    /// </summary>
+    [TestCleanup]
+    public void TestCleanup()
+    {
+      TestUtilities.CleanUpVisualStudioInstance(dte_);
+    }
+
+    /// <summary>
+    /// A test for WebServer Constructor. Starts the web server.
+    /// </summary>
+    [TestMethod]
+    public void WebServerConstructorTest()
+    {
+      OutputWindowPane outputWindowPane = dte_.ToolWindows.OutputWindow.OutputWindowPanes.Add(
+          Strings.WebServerOutputWindowTitle);
+
+      // Set up mock property manager to return the desired property values.
+      MockPropertyManager properties = new MockPropertyManager(
+        PropertyManager.ProjectPlatformType.Pepper,
+        delegate(string page, string name)
+        {
+          switch (page)
+          {
+            case "ConfigurationGeneral":
+              switch (name)
+              {
+                case "VSNaClSDKRoot": return System.Environment.GetEnvironmentVariable(
+                    NativeClientVSAddIn.Strings.SDKPathEnvironmentVariable);
+                case "NaClWebServerPort": return "5105";
+              }
+
+              break;
+            case "Property":
+              switch (name)
+              {
+                case "ProjectDirectory": return TestContext.DeploymentDirectory;
+              }
+
+              break;
+          }
+
+          return null;
+        },
+        null);
+
+      WebServer target = null;
+      try
+      {
+        target = new WebServer(outputWindowPane, properties);
+
+        TestUtilities.AssertTrueWithTimeout(
+          () => !string.IsNullOrEmpty(TestUtilities.GetPaneText(outputWindowPane)),
+          TimeSpan.FromMilliseconds(500),
+          20,
+          "Pane text never appeared");
+
+        TestUtilities.AssertTrueWithTimeout(
+            () => TestUtilities.DoesProcessExist("python.exe", "5105", "httpd.py"),
+            TimeSpan.FromMilliseconds(500),
+            20,
+            "Web server failed to start.");
+
+        target.Dispose();
+
+        TestUtilities.AssertTrueWithTimeout(
+            () => !TestUtilities.DoesProcessExist("python.exe", "5105", "httpd.py"),
+            TimeSpan.FromMilliseconds(500),
+            20,
+            "Web server failed to shut down.");
+      }
+      finally
+      {
+        if (target != null)
+        {
+          target.Dispose();
+        }
+      }
+    }
+  }
+}
diff --git a/check_test_results.py b/check_test_results.py
index 09172b5..a4542a3 100644
--- a/check_test_results.py
+++ b/check_test_results.py
@@ -1,49 +1,49 @@
-#!/usr/bin/env python

-# Copyright (c) 2012 The Chromium Authors. All rights reserved.

-# Use of this source code is governed by a BSD-style license that can be

-# found in the LICENSE file.

-

-""" This script will parse the results file produced by MSTest.

-

-The script takes a single argument containing the path to the Results.trx

-file to parse. It will log relevant test run information, and exit with code 0

-if all tests passed, or code 1 if some test failed.

-"""

-

-import sys

-import xml.etree.ElementTree

-

-MSTEST_NAMESPACE = 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010'

-

-def main():

-  if len(sys.argv) < 2:

-    print 'Must provide path to the Results.trx file'

-    return 1

-

-  # Parse the xml results file

-  tree = xml.etree.ElementTree.parse(sys.argv[1])

-  root = tree.getroot()

-  results_node = root.find('{%s}Results' % MSTEST_NAMESPACE)

-  results = results_node.findall('{%s}UnitTestResult' % MSTEST_NAMESPACE)

-  test_run_name = root.attrib['name']

-

-  exit_code = 0

-

-  # Print the results, note any failures by setting exit_code to 1

-  print test_run_name

-  for result in results:

-    fail_message = 'None.'

-    if result.attrib['outcome'] != 'Passed':

-      exit_code = 1

-      fail_element = result.find('{%s}Output/{%s}ErrorInfo/{%s}Message' % (

-          MSTEST_NAMESPACE, MSTEST_NAMESPACE, MSTEST_NAMESPACE))

-      if fail_element is not None:

-        fail_message = fail_element.text

-    print 'Test: %s, Duration: %s, Outcome: %s, Reason: %s\n' % (

-        result.attrib['testName'], result.attrib['duration'],

-        result.attrib['outcome'], fail_message)

-

-  return exit_code

-

-if __name__ == '__main__':

-  sys.exit(main())

+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" This script will parse the results file produced by MSTest.
+
+The script takes a single argument containing the path to the Results.trx
+file to parse. It will log relevant test run information, and exit with code 0
+if all tests passed, or code 1 if some test failed.
+"""
+
+import sys
+import xml.etree.ElementTree
+
+MSTEST_NAMESPACE = 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010'
+
+def main():
+  if len(sys.argv) < 2:
+    print 'Must provide path to the Results.trx file'
+    return 1
+
+  # Parse the xml results file
+  tree = xml.etree.ElementTree.parse(sys.argv[1])
+  root = tree.getroot()
+  results_node = root.find('{%s}Results' % MSTEST_NAMESPACE)
+  results = results_node.findall('{%s}UnitTestResult' % MSTEST_NAMESPACE)
+  test_run_name = root.attrib['name']
+
+  exit_code = 0
+
+  # Print the results, note any failures by setting exit_code to 1
+  print test_run_name
+  for result in results:
+    fail_message = 'None.'
+    if result.attrib['outcome'] != 'Passed':
+      exit_code = 1
+      fail_element = result.find('{%s}Output/{%s}ErrorInfo/{%s}Message' % (
+          MSTEST_NAMESPACE, MSTEST_NAMESPACE, MSTEST_NAMESPACE))
+      if fail_element is not None:
+        fail_message = fail_element.text
+    print 'Test: %s, Duration: %s, Outcome: %s, Reason: %s\n' % (
+        result.attrib['testName'], result.attrib['duration'],
+        result.attrib['outcome'], fail_message)
+
+  return exit_code
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/create_package.py b/create_package.py
index da135b8..018faa8 100644
--- a/create_package.py
+++ b/create_package.py
@@ -1,124 +1,124 @@
-#!/usr/bin/env python

-# Copyright (c) 2012 The Chromium Authors. All rights reserved.

-# Use of this source code is governed by a BSD-style license that can be

-# found in the LICENSE file.

-

-"""Takes the output of the build step and zips the distributable package.

-

-This script assumes the build script has been run to compile the add-in.

-It zips up all files required for the add-in installation and places the

-result in out/NativeClientVSAddin.zip

-"""

-

-import os

-import re

-import fileinput

-import win32api

-import shutil

-import zipfile

-

-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

-

-# Root output directory.

-BUILD_OUTPUT_DIRECTORY = os.path.join(

-    SCRIPT_DIR,

-    "../../out/NativeClientVSAddIn")

-

-# Directory that contains the build assemblies.

-ASSEMBLY_DIRECTORY = os.path.join(BUILD_OUTPUT_DIRECTORY, "Debug")

-

-# Directory containing static installer resources.

-RESOURCE_DIRECTORY = os.path.join(SCRIPT_DIR, "InstallerResources")

-

-# Base name of the final zip file.

-OUTPUT_NAME = os.path.join(BUILD_OUTPUT_DIRECTORY, "NativeClientVSAddIn.zip")

-

-# AddIn metadata file path. We will modify this with the version #.

-ADDIN_METADATA = os.path.join(RESOURCE_DIRECTORY, "NativeClientVSAddIn.AddIn")

-

-# AddIn dll file path. We will obtain our add-in version from this.

-ADDIN_ASSEMBLY = os.path.join(ASSEMBLY_DIRECTORY, "NativeClientVSAddIn.dll")

-

-# Regex list to exclude from the zip. If a file path matches any of the

-# expressions during a call to AddFolderToZip it is excluded from the zip file.

-EXCLUDES = [

-    '.*\.svn.*', # Exclude .svn directories.

-    # Exclude .AddIn file for now since we need to modify it with version info.

-    re.escape(ADDIN_METADATA)]

-

-# List of source/destination pairs to include in zip file.

-FILE_LIST = [

-  (ADDIN_ASSEMBLY, ''),

-  (os.path.join(ASSEMBLY_DIRECTORY, "NaCl.Build.CPPTasks.dll"), 'NaCl')]

-

-

-def AddFolderToZip(path, zip_file):

-  """Adds an entire folder and sub folders to an open zipfile object.

-

-  The zip_file must already be open and it is not closed by this function.

-

-  Args:

-    path: Folder to add.

-    zipfile: Already open zip file.

-

-  Returns:

-    Nothing.

-  """

-  # Ensure the path ends in trailing slash.

-  path = path.rstrip("/\\") + "\\"

-  for dir_path, dir_names, files in os.walk(path):

-    for file in files:

-      read_path = os.path.join(dir_path, file)

-

-      # If the file path matches an exclude, don't include it.

-      if any(re.search(expr, read_path) is not None for expr in EXCLUDES):

-        continue

-

-      zip_based_dir = dir_path[len(path):]

-      write_path = os.path.join(zip_based_dir, file)

-      zip_file.write(read_path, write_path, zipfile.ZIP_DEFLATED)

-

-

-def AddVersionModifiedAddinFile(zip_file):

-  """Modifies the .AddIn file with the build version and adds to the zip.

-

-  The version number is obtained from the NativeClientAddIn.dll assembly which

-  is built during the build process.

-

-  Args:

-  zip_file: Already open zip file.

-  """

-  info = win32api.GetFileVersionInfo(ADDIN_ASSEMBLY, "\\")

-  ms = info['FileVersionMS']

-  ls = info['FileVersionLS']

-  version = "[%i.%i.%i.%i]" % (

-      win32api.HIWORD(ms), win32api.LOWORD(ms),

-      win32api.HIWORD(ls), win32api.LOWORD(ls))

-  print "\nNaCl VS Add-in Build version: %s\n" % (version)

-

-  metadata_filename = os.path.basename(ADDIN_METADATA)

-  modified_file = os.path.join(ASSEMBLY_DIRECTORY, metadata_filename)

-

-  # Copy the metadata file to new location and modify the version info.

-  with open(ADDIN_METADATA, 'r') as source_file:

-    with open(modified_file, 'w') as dest_file:

-      for line in source_file:

-        dest_file.write(line.replace("[REPLACE_ADDIN_VERSION]", version))

-

-  zip_file.write(modified_file, metadata_filename, zipfile.ZIP_DEFLATED)

-

-

-def main():

-  # Zip the package.

-  out_file = zipfile.ZipFile(OUTPUT_NAME, 'w')

-  for source_dest in FILE_LIST:

-    file_name = os.path.basename(source_dest[0])

-    dest = os.path.join(source_dest[1], file_name)

-    out_file.write(source_dest[0], dest, zipfile.ZIP_DEFLATED)

-  AddFolderToZip(RESOURCE_DIRECTORY, out_file)

-  AddVersionModifiedAddinFile(out_file)

-  out_file.close()

-

-

-if __name__ == '__main__':

-  main()

+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Takes the output of the build step and zips the distributable package.
+
+This script assumes the build script has been run to compile the add-in.
+It zips up all files required for the add-in installation and places the
+result in out/NativeClientVSAddin.zip
+"""
+
+import os
+import re
+import fileinput
+import win32api
+import shutil
+import zipfile
+
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+# Root output directory.
+BUILD_OUTPUT_DIRECTORY = os.path.join(
+    SCRIPT_DIR,
+    "../../out/NativeClientVSAddIn")
+
+# Directory that contains the build assemblies.
+ASSEMBLY_DIRECTORY = os.path.join(BUILD_OUTPUT_DIRECTORY, "Debug")
+
+# Directory containing static installer resources.
+RESOURCE_DIRECTORY = os.path.join(SCRIPT_DIR, "InstallerResources")
+
+# Base name of the final zip file.
+OUTPUT_NAME = os.path.join(BUILD_OUTPUT_DIRECTORY, "NativeClientVSAddIn.zip")
+
+# AddIn metadata file path. We will modify this with the version #.
+ADDIN_METADATA = os.path.join(RESOURCE_DIRECTORY, "NativeClientVSAddIn.AddIn")
+
+# AddIn dll file path. We will obtain our add-in version from this.
+ADDIN_ASSEMBLY = os.path.join(ASSEMBLY_DIRECTORY, "NativeClientVSAddIn.dll")
+
+# Regex list to exclude from the zip. If a file path matches any of the
+# expressions during a call to AddFolderToZip it is excluded from the zip file.
+EXCLUDES = [
+    '.*\.svn.*', # Exclude .svn directories.
+    # Exclude .AddIn file for now since we need to modify it with version info.
+    re.escape(ADDIN_METADATA)]
+
+# List of source/destination pairs to include in zip file.
+FILE_LIST = [
+  (ADDIN_ASSEMBLY, ''),
+  (os.path.join(ASSEMBLY_DIRECTORY, "NaCl.Build.CPPTasks.dll"), 'NaCl')]
+
+
+def AddFolderToZip(path, zip_file):
+  """Adds an entire folder and sub folders to an open zipfile object.
+
+  The zip_file must already be open and it is not closed by this function.
+
+  Args:
+    path: Folder to add.
+    zipfile: Already open zip file.
+
+  Returns:
+    Nothing.
+  """
+  # Ensure the path ends in trailing slash.
+  path = path.rstrip("/\\") + "\\"
+  for dir_path, dir_names, files in os.walk(path):
+    for file in files:
+      read_path = os.path.join(dir_path, file)
+
+      # If the file path matches an exclude, don't include it.
+      if any(re.search(expr, read_path) is not None for expr in EXCLUDES):
+        continue
+
+      zip_based_dir = dir_path[len(path):]
+      write_path = os.path.join(zip_based_dir, file)
+      zip_file.write(read_path, write_path, zipfile.ZIP_DEFLATED)
+
+
+def AddVersionModifiedAddinFile(zip_file):
+  """Modifies the .AddIn file with the build version and adds to the zip.
+
+  The version number is obtained from the NativeClientAddIn.dll assembly which
+  is built during the build process.
+
+  Args:
+  zip_file: Already open zip file.
+  """
+  info = win32api.GetFileVersionInfo(ADDIN_ASSEMBLY, "\\")
+  ms = info['FileVersionMS']
+  ls = info['FileVersionLS']
+  version = "[%i.%i.%i.%i]" % (
+      win32api.HIWORD(ms), win32api.LOWORD(ms),
+      win32api.HIWORD(ls), win32api.LOWORD(ls))
+  print "\nNaCl VS Add-in Build version: %s\n" % (version)
+
+  metadata_filename = os.path.basename(ADDIN_METADATA)
+  modified_file = os.path.join(ASSEMBLY_DIRECTORY, metadata_filename)
+
+  # Copy the metadata file to new location and modify the version info.
+  with open(ADDIN_METADATA, 'r') as source_file:
+    with open(modified_file, 'w') as dest_file:
+      for line in source_file:
+        dest_file.write(line.replace("[REPLACE_ADDIN_VERSION]", version))
+
+  zip_file.write(modified_file, metadata_filename, zipfile.ZIP_DEFLATED)
+
+
+def main():
+  # Zip the package.
+  out_file = zipfile.ZipFile(OUTPUT_NAME, 'w')
+  for source_dest in FILE_LIST:
+    file_name = os.path.basename(source_dest[0])
+    dest = os.path.join(source_dest[1], file_name)
+    out_file.write(source_dest[0], dest, zipfile.ZIP_DEFLATED)
+  AddFolderToZip(RESOURCE_DIRECTORY, out_file)
+  AddVersionModifiedAddinFile(out_file)
+  out_file.close()
+
+
+if __name__ == '__main__':
+  main()