context: /****************************************************************************
  **
  ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/legal
  **
  ** This file is part of the Qt VS Add-in.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** Commercial License Usage
  ** Licensees holding valid commercial Qt licenses may use this file in
  ** accordance with the commercial license agreement provided with the
  ** Software or, alternatively, in accordance with the terms contained in
  ** a written agreement between you and Digia.  For licensing terms and
  ** conditions see http://qt.digia.com/licensing.  For further information
  ** use the contact form at http://qt.digia.com/contact-us.
  **
  ** GNU Lesser General Public License Usage
  ** Alternatively, this file may be used under the terms of the GNU Lesser
  ** General Public License version 2.1 as published by the Free Software
  ** Foundation and appearing in the file LICENSE.LGPL included in the
  ** packaging of this file.  Please review the following information to
  ** ensure the GNU Lesser General Public License version 2.1 requirements
  ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  **
  ** In addition, as a special exception, Digia gives you certain additional
  ** rights.  These rights are described in the Digia Qt LGPL Exception
  ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  **
  ** GNU General Public License Usage
  ** Alternatively, this file may be used under the terms of the GNU
  ** General Public License version 3.0 as published by the Free Software
  ** Foundation and appearing in the file LICENSE.GPL included in the
  ** packaging of this file.  Please review the following information to
  ** ensure the GNU General Public License version 3.0 requirements will be
  ** met: http://www.gnu.org/copyleft/gpl.html.
  **
  **
  ** $QT_END_LICENSE$
  **
  ****************************************************************************/
  
  using System;
  using System.IO;
  using System.Collections.Generic;
  
  namespace Digia.Qt5ProjectLib
  {
      using Microsoft.VisualStudio.VCProjectEngine;
  
      /// <summary>
      /// Wrapper for the VCCLCompilerTool class.
      /// </summary>
      /// For platforms other than Win32 the type VCCLCompilerTool is not available.
      /// See http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=220646&SiteID=1
      /// So we have to use the reflection system to get and set the desired properties.
      /// This class should be the only place where VCCLCompilerTool is used.
      /// Using VCCLCompilerTool directly will break the VS integration for Win CE.
      class CompilerToolWrapper
      {
          private VCCLCompilerTool compilerTool;
          private Object compilerObj;
          private Type compilerType;
  
          public static CompilerToolWrapper Create(VCConfiguration config)
          {
              CompilerToolWrapper wrapper = null;
              try
              {
                  wrapper = new CompilerToolWrapper(((IVCCollection)config.Tools).Item("VCCLCompilerTool"));
              }
              catch
              {
              }
  
              return wrapper.IsNull() ? null : wrapper;
          }
  
          public static CompilerToolWrapper Create(VCFileConfiguration config)
          {
              CompilerToolWrapper wrapper = null;
              try
              {
                  wrapper = new CompilerToolWrapper(config.Tool);
              }
              catch
              {
              }
  
              return wrapper.IsNull() ? null : wrapper;
          }
  
          public static CompilerToolWrapper Create(VCPropertySheet sheet)
          {
              CompilerToolWrapper wrapper = null;
              try
              {
                  wrapper = new CompilerToolWrapper(((IVCCollection)sheet.Tools).Item("VCCLCompilerTool"));
              }
              catch
              {
              }
  
              return wrapper.IsNull() ? null : wrapper;
          }
  
          protected CompilerToolWrapper(object tool)
          {
              if (tool == null)
                  return;
  
              compilerTool = tool as VCCLCompilerTool;
              if (compilerTool == null)
              {
                  compilerObj = tool;
                  compilerType = compilerObj.GetType();
              }
          }
  
          protected bool IsNull()
          {
              return compilerTool == null && compilerObj == null;
          }
  
          public string ObjectFile
          {
              get
              {
                  if (compilerTool != null)
                      return compilerTool.ObjectFile;
                  else
                      return GetStringProperty("ObjectFile");
              }
  
              set
              {
                  if (compilerTool != null)
                      compilerTool.ObjectFile = value;
                  else
                      SetStringProperty("ObjectFile", value);
              }
          }
  
          public string ProgramDataBaseFileName
          {
              get
              {
                  if (compilerTool != null)
                      return compilerTool.ProgramDataBaseFileName;
                  else
                      return GetStringProperty("ProgramDataBaseFileName");
              }
  
              set
              {
                  if (compilerTool != null)
                      compilerTool.ProgramDataBaseFileName = value;
                  else
                      SetStringProperty("ProgramDataBaseFileName", value);
              }
          }
  
          public List<string> AdditionalIncludeDirectories
          {
              get
              {
                  string directories = GetAdditionalIncludeDirectories();
                  if (directories == null)
                      return new List<string>();
  #if (VS2010 || VS2012 || VS2013)
                  // double quotes are escaped
                  directories = directories.Replace("\\\"", "\"");
  #endif
                  string[] dirArray = directories.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
                  List<string> lst = new List<string>(dirArray);
                  int i = 0;
                  while (i < lst.Count)
                  {
                      string item = lst[i];
                      if (item.StartsWith("\"") && item.EndsWith("\""))
                      {
                          item = item.Remove(0, 1);
                          item = item.Remove(item.Length - 1, 1);
                          lst[i] = item;
                      }
  
                      if (lst[i].Length > 0)
                          ++i;
                      else
                          lst.RemoveAt(i);
                  }
                  return lst;
              }
  
              set
              {
                  if (value == null)
                  {
                      SetAdditionalIncludeDirectories(null);
                      return;
                  }
                  string newDirectories = "";
                  bool firstLoop = true;
                  foreach (string dir in value)
                  {
                      if (firstLoop)
                          firstLoop = false;
                      else
                          newDirectories += ";";
  
                      if (dir.IndexOfAny(new char[] { ' ', '\t' }) > 0 || !Path.IsPathRooted(dir))
                          newDirectories += "\"" + dir + "\"";
                      else
                          newDirectories += dir;
                  }
                  if (newDirectories != GetAdditionalIncludeDirectories())
                      SetAdditionalIncludeDirectories(newDirectories);
              }
          }
  
          public void SetAdditionalIncludeDirectories(string value)
          {
              // Prevent setting of empty substring, as they break the build
              value = value.Replace("\"\",", "");
              if (compilerTool != null)
                  compilerTool.AdditionalIncludeDirectories = value;
              else
                  SetStringProperty("AdditionalIncludeDirectories", value);
          }
  
          public List<string> PreprocessorDefinitions
          {
              get
              {
                  string ppdefsstr = GetPreprocessorDefinitions();
                  if (String.IsNullOrEmpty(ppdefsstr))
                      return new List<string>();
  
                  string[] ppdefs = ppdefsstr.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
                  return new List<string>(ppdefs);
              }
  
              set
              {
                  if (value == null)
                  {
                      SetPreprocessorDefinitions("");
                  }
                  else
                  {
                      string ppdefsstr = "";
                      bool firstLoop = true;
                      foreach (string ppdef in value)
                      {
                          if (firstLoop)
                              firstLoop = false;
                          else
                              ppdefsstr += ",";
                          ppdefsstr += ppdef;
                      }
                      SetPreprocessorDefinitions(ppdefsstr);
                  }
              }
          }
  
          /// <summary>
          /// Adds a single preprocessor definition.
          /// </summary>
          /// <param name="value"></param>
          public void AddPreprocessorDefinition(string value)
          {
              string preprocessorDefs = GetPreprocessorDefinitions();
              if (preprocessorDefs != null)
              {
                  string[] definesArray = preprocessorDefs.Split(new char[] {';', ','}, StringSplitOptions.RemoveEmptyEntries);
                  List<string> definesList = new List<string>(definesArray);
                  if (definesList.Contains(value))
                      return;
                  if (preprocessorDefs.Length > 0 && !preprocessorDefs.EndsWith(";") && !value.StartsWith(";"))
                      preprocessorDefs += ";";
              }
              preprocessorDefs += value;
              SetPreprocessorDefinitions(preprocessorDefs);
          }
  
          /// <summary>
          /// Removes a single preprocessor definition.
          /// </summary>
          /// <param name="value"></param>
          public void RemovePreprocessorDefinition(string value)
          {
              string preprocessorDefs = GetPreprocessorDefinitions();
              if (preprocessorDefs == null)
                  return;
  
              string[] definesArray = preprocessorDefs.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
  
gt:             List<string> definesList = new List<string>(definesArray);