15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "tools/gn/substitution_pattern.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "tools/gn/build_settings.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "tools/gn/err.h" 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "tools/gn/filesystem_utils.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "tools/gn/value.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SubstitutionPattern::Subrange::Subrange() 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : type(SUBSTITUTION_LITERAL) { 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SubstitutionPattern::Subrange::Subrange(SubstitutionType t, 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& l) 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : type(t), 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) literal(l) { 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SubstitutionPattern::Subrange::~Subrange() { 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)SubstitutionPattern::SubstitutionPattern() : origin_(NULL) { 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SubstitutionPattern::~SubstitutionPattern() { 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool SubstitutionPattern::Parse(const Value& value, Err* err) { 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!value.VerifyTypeIs(Value::STRING, err)) 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Parse(value.string_value(), value.origin(), err); 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool SubstitutionPattern::Parse(const std::string& str, 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const ParseNode* origin, 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Err* err) { 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(ranges_.empty()); // Should only be called once. 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t cur = 0; 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (true) { 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t next = str.find("{{", cur); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Pick up everything from the previous spot to here as a literal. 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (next == std::string::npos) { 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (cur != str.size()) 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ranges_.push_back(Subrange(SUBSTITUTION_LITERAL, str.substr(cur))); 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (next > cur) { 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ranges_.push_back( 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Subrange(SUBSTITUTION_LITERAL, str.substr(cur, next - cur))); 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Find which specific pattern this corresponds to. 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool found_match = false; 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = SUBSTITUTION_FIRST_PATTERN; 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) i < SUBSTITUTION_NUM_TYPES; i++) { 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char* cur_pattern = kSubstitutionNames[i]; 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t cur_len = strlen(cur_pattern); 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (str.compare(next, cur_len, cur_pattern) == 0) { 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ranges_.push_back(Subrange(static_cast<SubstitutionType>(i))); 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cur = next + cur_len; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) found_match = true; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Expect all occurrances of {{ to resolve to a pattern. 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!found_match) { 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Could make this error message more friendly if it comes up a lot. But 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // most people will not be writing substitution patterns and the code 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // to exactly indicate the error location is tricky. 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *err = Err(origin, "Unknown substitution pattern", 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Found a {{ at offset " + 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::SizeTToString(next) + 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) " and did not find a known substitution following it."); 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ranges_.clear(); 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) origin_ = origin; 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Fill required types vector. 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SubstitutionBits bits; 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FillRequiredTypes(&bits); 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bits.FillVector(&required_types_); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciSubstitutionPattern SubstitutionPattern::MakeForTest(const char* str) { 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Err err; 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SubstitutionPattern pattern; 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(pattern.Parse(str, NULL, &err)) << err.message(); 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return pattern; 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)std::string SubstitutionPattern::AsString() const { 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string result; 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < ranges_.size(); i++) { 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ranges_[i].type == SUBSTITUTION_LITERAL) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result.append(ranges_[i].literal); 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result.append(kSubstitutionNames[ranges_[i].type]); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return result; 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void SubstitutionPattern::FillRequiredTypes(SubstitutionBits* bits) const { 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < ranges_.size(); i++) { 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ranges_[i].type != SUBSTITUTION_LITERAL) 11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bits->used[static_cast<size_t>(ranges_[i].type)] = true; 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool SubstitutionPattern::IsInOutputDir(const BuildSettings* build_settings, 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Err* err) const { 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (ranges_.empty()) { 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *err = Err(origin_, "This is empty but I was expecting an output file."); 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (ranges_[0].type == SUBSTITUTION_LITERAL) { 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If the first thing is a literal, it must start with the output dir. 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!EnsureStringIsInOutputDir( 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) build_settings->build_dir(), 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ranges_[0].literal, origin_, err)) 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Otherwise, the first subrange must be a pattern that expands to 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // something in the output directory. 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!SubstitutionIsInOutputDir(ranges_[0].type)) { 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *err = Err(origin_, 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "File is not inside output directory.", 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "The given file should be in the output directory. Normally you\n" 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "would specify\n\"$target_out_dir/foo\" or " 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "\"{{source_gen_dir}}/foo\"."); 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 148