// Copyright (c) 2013 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/escape.h"

#include <stddef.h>

#include "base/containers/stack_container.h"
#include "base/logging.h"
#include "build/build_config.h"

namespace {

// A "1" in this lookup table means that char is valid in the Posix shell.
const char kShellValid[0x80] = {
// 00-1f: all are invalid
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// ' ' !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
//  0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0,
//  @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
//  P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]  ^  _
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
//  `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
//  p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0 };

// Append one character to the given string, escaping it for Ninja.
//
// Ninja's escaping rules are very simple. We always escape colons even
// though they're OK in many places, in case the resulting string is used on
// the left-hand-side of a rule.
template<typename DestString>
inline void NinjaEscapeChar(char ch, DestString* dest) {
  if (ch == '$' || ch == ' ' || ch == ':')
    dest->push_back('$');
  dest->push_back(ch);
}

template<typename DestString>
void EscapeStringToString_Ninja(const base::StringPiece& str,
                                const EscapeOptions& options,
                                DestString* dest,
                                bool* needed_quoting) {
  for (const auto& elem : str)
    NinjaEscapeChar(elem, dest);
}

template<typename DestString>
void EscapeStringToString_NinjaPreformatted(const base::StringPiece& str,
                                            DestString* dest) {
  // Only Ninja-escape $.
  for (const auto& elem : str) {
    if (elem == '$')
      dest->push_back('$');
    dest->push_back(elem);
  }
}

// Escape for CommandLineToArgvW and additionally escape Ninja characters.
//
// The basic algorithm is if the string doesn't contain any parse-affecting
// characters, don't do anything (other than the Ninja processing). If it does,
// quote the string, and backslash-escape all quotes and backslashes.
// See:
//   http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
//   http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
template<typename DestString>
void EscapeStringToString_WindowsNinjaFork(const base::StringPiece& str,
                                           const EscapeOptions& options,
                                           DestString* dest,
                                           bool* needed_quoting) {
  // We assume we don't have any whitespace chars that aren't spaces.
  DCHECK(str.find_first_of("\r\n\v\t") == std::string::npos);

  if (str.find_first_of(" \"") == std::string::npos) {
    // Simple case, don't quote.
    EscapeStringToString_Ninja(str, options, dest, needed_quoting);
  } else {
    if (!options.inhibit_quoting)
      dest->push_back('"');

    for (size_t i = 0; i < str.size(); i++) {
      // Count backslashes in case they're followed by a quote.
      size_t backslash_count = 0;
      while (i < str.size() && str[i] == '\\') {
        i++;
        backslash_count++;
      }
      if (i == str.size()) {
        // Backslashes at end of string. Backslash-escape all of them since
        // they'll be followed by a quote.
        dest->append(backslash_count * 2, '\\');
      } else if (str[i] == '"') {
        // 0 or more backslashes followed by a quote. Backslash-escape the
        // backslashes, then backslash-escape the quote.
        dest->append(backslash_count * 2 + 1, '\\');
        dest->push_back('"');
      } else {
        // Non-special Windows character, just escape for Ninja. Also, add any
        // backslashes we read previously, these are literals.
        dest->append(backslash_count, '\\');
        NinjaEscapeChar(str[i], dest);
      }
    }

    if (!options.inhibit_quoting)
      dest->push_back('"');
    if (needed_quoting)
      *needed_quoting = true;
  }
}

template<typename DestString>
void EscapeStringToString_PosixNinjaFork(const base::StringPiece& str,
                                         const EscapeOptions& options,
                                         DestString* dest,
                                         bool* needed_quoting) {
  for (const auto& elem : str) {
    if (elem == '$' || elem == ' ') {
      // Space and $ are special to both Ninja and the shell. '$' escape for
      // Ninja, then backslash-escape for the shell.
      dest->push_back('\\');
      dest->push_back('$');
      dest->push_back(elem);
    } else if (elem == ':') {
      // Colon is the only other Ninja special char, which is not special to
      // the shell.
      dest->push_back('$');
      dest->push_back(':');
    } else if (static_cast<unsigned>(elem) >= 0x80 ||
               !kShellValid[static_cast<int>(elem)]) {
      // All other invalid shell chars get backslash-escaped.
      dest->push_back('\\');
      dest->push_back(elem);
    } else {
      // Everything else is a literal.
      dest->push_back(elem);
    }
  }
}

template<typename DestString>
void EscapeStringToString(const base::StringPiece& str,
                          const EscapeOptions& options,
                          DestString* dest,
                          bool* needed_quoting) {
  switch (options.mode) {
    case ESCAPE_NONE:
      dest->append(str.data(), str.size());
      break;
    case ESCAPE_NINJA:
      EscapeStringToString_Ninja(str, options, dest, needed_quoting);
      break;
    case ESCAPE_NINJA_COMMAND:
      switch (options.platform) {
        case ESCAPE_PLATFORM_CURRENT:
#if defined(OS_WIN)
          EscapeStringToString_WindowsNinjaFork(str, options, dest,
                                                needed_quoting);
#else
          EscapeStringToString_PosixNinjaFork(str, options, dest,
                                              needed_quoting);
#endif
          break;
        case ESCAPE_PLATFORM_WIN:
          EscapeStringToString_WindowsNinjaFork(str, options, dest,
                                                needed_quoting);
          break;
        case ESCAPE_PLATFORM_POSIX:
          EscapeStringToString_PosixNinjaFork(str, options, dest,
                                              needed_quoting);
          break;
        default:
          NOTREACHED();
      }
      break;
    case ESCAPE_NINJA_PREFORMATTED_COMMAND:
      EscapeStringToString_NinjaPreformatted(str, dest);
      break;
    default:
      NOTREACHED();
  }
}

}  // namespace

std::string EscapeString(const base::StringPiece& str,
                         const EscapeOptions& options,
                         bool* needed_quoting) {
  std::string result;
  result.reserve(str.size() + 4);  // Guess we'll add a couple of extra chars.
  EscapeStringToString(str, options, &result, needed_quoting);
  return result;
}

void EscapeStringToStream(std::ostream& out,
                          const base::StringPiece& str,
                          const EscapeOptions& options) {
  base::StackString<256> escaped;
  EscapeStringToString(str, options, &escaped.container(), nullptr);
  if (!escaped->empty())
    out.write(escaped->data(), escaped->size());
}
