| // Copyright 2016 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. | 
 |  | 
 | #include "tools/gn/visual_studio_utils.h" | 
 |  | 
 | #include <vector> | 
 |  | 
 | #include "base/md5.h" | 
 | #include "base/strings/string_split.h" | 
 | #include "base/strings/string_util.h" | 
 |  | 
 | CompilerOptions::CompilerOptions() = default; | 
 |  | 
 | CompilerOptions::~CompilerOptions() = default; | 
 |  | 
 | LinkerOptions::LinkerOptions() = default; | 
 |  | 
 | LinkerOptions::~LinkerOptions() = default; | 
 |  | 
 | std::string MakeGuid(const std::string& entry_path, const std::string& seed) { | 
 |   std::string str = base::ToUpperASCII(base::MD5String(seed + entry_path)); | 
 |   return '{' + str.substr(0, 8) + '-' + str.substr(8, 4) + '-' + | 
 |          str.substr(12, 4) + '-' + str.substr(16, 4) + '-' + | 
 |          str.substr(20, 12) + '}'; | 
 | } | 
 |  | 
 | #define SetOption(condition, member, value) \ | 
 |   if (condition) {                          \ | 
 |     options->member = value;                \ | 
 |     return;                                 \ | 
 |   } | 
 |  | 
 | #define AppendOption(condition, member, value, separator) \ | 
 |   if (condition) {                                        \ | 
 |     options->member += value + separator;                 \ | 
 |     return;                                               \ | 
 |   } | 
 |  | 
 | void ParseCompilerOption(const std::string& cflag, CompilerOptions* options) { | 
 |   if (cflag.size() > 2 && cflag[0] == '/') { | 
 |     switch (cflag[1]) { | 
 |       case 'F': | 
 |         AppendOption(cflag.size() > 3 && cflag[2] == 'I', forced_include_files, | 
 |                      cflag.substr(3), ';') | 
 |         break; | 
 |  | 
 |       case 'G': | 
 |         if (cflag[2] == 'S') { | 
 |           SetOption(cflag.size() == 3, buffer_security_check, "true") | 
 |           SetOption(cflag.size() == 4 && cflag[3] == '-', | 
 |                     buffer_security_check, "false") | 
 |         } | 
 |         break; | 
 |  | 
 |       case 'M': | 
 |         switch (cflag[2]) { | 
 |           case 'D': | 
 |             SetOption(cflag.size() == 3, runtime_library, "MultiThreadedDLL") | 
 |             SetOption(cflag.size() == 4 && cflag[3] == 'd', runtime_library, | 
 |                       "MultiThreadedDebugDLL") | 
 |             break; | 
 |  | 
 |           case 'T': | 
 |             SetOption(cflag.size() == 3, runtime_library, "MultiThreaded") | 
 |             SetOption(cflag.size() == 4 && cflag[3] == 'd', runtime_library, | 
 |                       "MultiThreadedDebug") | 
 |             break; | 
 |         } | 
 |         break; | 
 |  | 
 |       case 'O': | 
 |         switch (cflag[2]) { | 
 |           case '1': | 
 |             SetOption(cflag.size() == 3, optimization, "MinSpace") | 
 |             break; | 
 |  | 
 |           case '2': | 
 |             SetOption(cflag.size() == 3, optimization, "MaxSpeed") | 
 |             break; | 
 |  | 
 |           case 'd': | 
 |             SetOption(cflag.size() == 3, optimization, "Disabled") | 
 |             break; | 
 |  | 
 |           case 'x': | 
 |             SetOption(cflag.size() == 3, optimization, "Full") | 
 |               break; | 
 |         } | 
 |         break; | 
 |  | 
 |       case 'T': | 
 |         // Skip flags that cause treating all source files as C and C++ files. | 
 |         if (cflag.size() == 3 && (cflag[2] == 'C' || cflag[2] == 'P')) | 
 |           return; | 
 |         break; | 
 |  | 
 |       case 'W': | 
 |         switch (cflag[2]) { | 
 |           case '0': | 
 |           case '1': | 
 |           case '2': | 
 |           case '3': | 
 |           case '4': | 
 |             SetOption(cflag.size() == 3, warning_level, | 
 |                       std::string("Level") + cflag[2]) | 
 |             break; | 
 |  | 
 |           case 'X': | 
 |             SetOption(cflag.size() == 3, treat_warning_as_error, "true") | 
 |             break; | 
 |         } | 
 |         break; | 
 |  | 
 |       case 'w': | 
 |         AppendOption(cflag.size() > 3 && cflag[2] == 'd', | 
 |                      disable_specific_warnings, cflag.substr(3), ';') | 
 |         break; | 
 |     } | 
 |   } | 
 |  | 
 |   // Put everything else into additional_options. | 
 |   options->additional_options += cflag + ' '; | 
 | } | 
 |  | 
 | // Parses |ldflags| value and stores it in |options|. | 
 | void ParseLinkerOption(const std::string& ldflag, LinkerOptions* options) { | 
 |   const char kSubsytemPrefix[] ="/SUBSYSTEM:"; | 
 |   if (base::StartsWith(ldflag, kSubsytemPrefix, | 
 |                        base::CompareCase::SENSITIVE)) { | 
 |     const std::string subsystem( | 
 |         ldflag.begin() + std::string(kSubsytemPrefix).length(), | 
 |         ldflag.end()); | 
 |     const std::vector<std::string> tokens = base::SplitString( | 
 |         subsystem, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | 
 |     if (!tokens.empty()) | 
 |       options->subsystem = tokens[0]; | 
 |   } | 
 | } |