 Chromium Code Reviews
 Chromium Code Reviews Issue 1546393002:
  Allow \n in GN string literals  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1546393002:
  Allow \n in GN string literals  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| Index: tools/gn/string_utils.cc | 
| diff --git a/tools/gn/string_utils.cc b/tools/gn/string_utils.cc | 
| index 5ee12d9dcea34402ae7a912f9dda470b2646af5a..7246f75933e72a58e702c5831e07b0f8922a1aac 100644 | 
| --- a/tools/gn/string_utils.cc | 
| +++ b/tools/gn/string_utils.cc | 
| @@ -5,7 +5,9 @@ | 
| #include "tools/gn/string_utils.h" | 
| #include <stddef.h> | 
| +#include <cctype> | 
| +#include "base/strings/string_number_conversions.h" | 
| #include "tools/gn/err.h" | 
| #include "tools/gn/input_file.h" | 
| #include "tools/gn/parser.h" | 
| @@ -131,7 +133,7 @@ bool AppendInterpolatedIdentifier(Scope* scope, | 
| // Handles string interpolations: $identifier and ${expression} | 
| // | 
| -// |*i| is the index into |input| of the $. This will be updated to point to | 
| +// |*i| is the index into |input| after the $. This will be updated to point to | 
| // the last character consumed on success. The token is the original string | 
| // to blame on failure. | 
| // | 
| @@ -143,13 +145,7 @@ bool AppendStringInterpolation(Scope* scope, | 
| size_t* i, | 
| std::string* output, | 
| Err* err) { | 
| - size_t dollars_index = *i; | 
| - (*i)++; | 
| - if (*i == size) { | 
| - *err = ErrInsideStringToken(token, dollars_index, 1, "$ at end of string.", | 
| - "I was expecting an identifier or {...} after the $."); | 
| - return false; | 
| - } | 
| + size_t dollars_index = *i - 1; | 
| if (input[*i] == '{') { | 
| // Bracketed expression. | 
| @@ -203,6 +199,40 @@ bool AppendStringInterpolation(Scope* scope, | 
| end_offset, output, err); | 
| } | 
| +// Handles a hex literal: $0xFF | 
| +// | 
| +// |*i| is the index into |input| after the $. This will be updated to point to | 
| +// the last character consumed on success. The token is the original string | 
| +// to blame on failure. | 
| +// | 
| +// On failure, returns false and sets the error. On success, appends the | 
| +// char with the given hex value to |*output|. | 
| +bool AppendHexByte(Scope* scope, | 
| + const Token& token, | 
| + const char* input, size_t size, | 
| + size_t* i, | 
| + std::string* output, | 
| + Err* err) { | 
| + size_t dollars_index = *i - 1; | 
| + // "$0" is already known to exist. | 
| + if (*i + 3 >= size || input[*i + 1] != 'x' || !std::isxdigit(input[*i + 2]) || | 
| + !std::isxdigit(input[*i + 3])) { | 
| + *err = ErrInsideStringToken( | 
| + token, dollars_index, *i - dollars_index + 1, | 
| + "Invalid hex character. Hex values must look like 0xFF."); | 
| + return false; | 
| + } | 
| + int value = 0; | 
| + if (!base::HexStringToInt(base::StringPiece(&input[*i + 2], 2), &value)) { | 
| + *err = ErrInsideStringToken(token, dollars_index, *i - dollars_index + 1, | 
| + "Could not convert hex value."); | 
| + return false; | 
| + } | 
| + *i += 3; | 
| + output->push_back(value); | 
| 
brettw
2016/01/05 18:11:04
I'm surprised you can push_back an into on a strin
 
agrieve
2016/01/05 19:43:19
Yeah, just tried both GCC and clang again but no w
 | 
| + return true; | 
| +} | 
| + | 
| } // namespace | 
| bool ExpandStringLiteral(Scope* scope, | 
| @@ -235,7 +265,16 @@ bool ExpandStringLiteral(Scope* scope, | 
| } | 
| output.push_back(input[i]); | 
| } else if (input[i] == '$') { | 
| - if (!AppendStringInterpolation(scope, literal, input, size, &i, | 
| + i++; | 
| + if (i == size) { | 
| + *err = ErrInsideStringToken(literal, i - 1, 1, "$ at end of string.", | 
| + "I was expecting an identifier, 0xFF, or {...} after the $."); | 
| + return false; | 
| + } | 
| + if (input[i] == '0') { | 
| + if (!AppendHexByte(scope, literal, input, size, &i, &output, err)) | 
| + return false; | 
| + } else if (!AppendStringInterpolation(scope, literal, input, size, &i, | 
| &output, err)) | 
| return false; | 
| } else { |