1 //===- FormatVariadic.cpp - Format string parsing and analysis ----*-C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 //===----------------------------------------------------------------------===// 7 8 #include "llvm/Support/FormatVariadic.h" 9 10 using namespace llvm; 11 12 static Optional<AlignStyle> translateLocChar(char C) { 13 switch (C) { 14 case '-': 15 return AlignStyle::Left; 16 case '=': 17 return AlignStyle::Center; 18 case '+': 19 return AlignStyle::Right; 20 default: 21 return None; 22 } 23 LLVM_BUILTIN_UNREACHABLE; 24 } 25 26 bool formatv_object_base::consumeFieldLayout(StringRef &Spec, AlignStyle &Where, 27 size_t &Align, char &Pad) { 28 Where = AlignStyle::Right; 29 Align = 0; 30 Pad = ' '; 31 if (Spec.empty()) 32 return true; 33 34 if (Spec.size() > 1) { 35 // A maximum of 2 characters at the beginning can be used for something 36 // other 37 // than the width. 38 // If Spec[1] is a loc char, then Spec[0] is a pad char and Spec[2:...] 39 // contains the width. 40 // Otherwise, if Spec[0] is a loc char, then Spec[1:...] contains the width. 41 // Otherwise, Spec[0:...] contains the width. 42 if (auto Loc = translateLocChar(Spec[1])) { 43 Pad = Spec[0]; 44 Where = *Loc; 45 Spec = Spec.drop_front(2); 46 } else if (auto Loc = translateLocChar(Spec[0])) { 47 Where = *Loc; 48 Spec = Spec.drop_front(1); 49 } 50 } 51 52 bool Failed = Spec.consumeInteger(0, Align); 53 return !Failed; 54 } 55 56 Optional<ReplacementItem> 57 formatv_object_base::parseReplacementItem(StringRef Spec) { 58 StringRef RepString = Spec.trim("{}"); 59 60 // If the replacement sequence does not start with a non-negative integer, 61 // this is an error. 62 char Pad = ' '; 63 std::size_t Align = 0; 64 AlignStyle Where = AlignStyle::Right; 65 StringRef Options; 66 size_t Index = 0; 67 RepString = RepString.trim(); 68 if (RepString.consumeInteger(0, Index)) { 69 assert(false && "Invalid replacement sequence index!"); 70 return ReplacementItem{}; 71 } 72 RepString = RepString.trim(); 73 if (!RepString.empty() && RepString.front() == ',') { 74 RepString = RepString.drop_front(); 75 if (!consumeFieldLayout(RepString, Where, Align, Pad)) 76 assert(false && "Invalid replacement field layout specification!"); 77 } 78 RepString = RepString.trim(); 79 if (!RepString.empty() && RepString.front() == ':') { 80 Options = RepString.drop_front().trim(); 81 RepString = StringRef(); 82 } 83 RepString = RepString.trim(); 84 if (!RepString.empty()) { 85 assert(false && "Unexpected characters found in replacement string!"); 86 } 87 88 return ReplacementItem{Spec, Index, Align, Where, Pad, Options}; 89 } 90 91 std::pair<ReplacementItem, StringRef> 92 formatv_object_base::splitLiteralAndReplacement(StringRef Fmt) { 93 std::size_t From = 0; 94 while (From < Fmt.size() && From != StringRef::npos) { 95 std::size_t BO = Fmt.find_first_of('{', From); 96 // Everything up until the first brace is a literal. 97 if (BO != 0) 98 return std::make_pair(ReplacementItem{Fmt.substr(0, BO)}, Fmt.substr(BO)); 99 100 StringRef Braces = 101 Fmt.drop_front(BO).take_while([](char C) { return C == '{'; }); 102 // If there is more than one brace, then some of them are escaped. Treat 103 // these as replacements. 104 if (Braces.size() > 1) { 105 size_t NumEscapedBraces = Braces.size() / 2; 106 StringRef Middle = Fmt.substr(BO, NumEscapedBraces); 107 StringRef Right = Fmt.drop_front(BO + NumEscapedBraces * 2); 108 return std::make_pair(ReplacementItem{Middle}, Right); 109 } 110 // An unterminated open brace is undefined. We treat the rest of the string 111 // as a literal replacement, but we assert to indicate that this is 112 // undefined and that we consider it an error. 113 std::size_t BC = Fmt.find_first_of('}', BO); 114 if (BC == StringRef::npos) { 115 assert( 116 false && 117 "Unterminated brace sequence. Escape with {{ for a literal brace."); 118 return std::make_pair(ReplacementItem{Fmt}, StringRef()); 119 } 120 121 // Even if there is a closing brace, if there is another open brace before 122 // this closing brace, treat this portion as literal, and try again with the 123 // next one. 124 std::size_t BO2 = Fmt.find_first_of('{', BO + 1); 125 if (BO2 < BC) 126 return std::make_pair(ReplacementItem{Fmt.substr(0, BO2)}, 127 Fmt.substr(BO2)); 128 129 StringRef Spec = Fmt.slice(BO + 1, BC); 130 StringRef Right = Fmt.substr(BC + 1); 131 132 auto RI = parseReplacementItem(Spec); 133 if (RI.hasValue()) 134 return std::make_pair(*RI, Right); 135 136 // If there was an error parsing the replacement item, treat it as an 137 // invalid replacement spec, and just continue. 138 From = BC + 1; 139 } 140 return std::make_pair(ReplacementItem{Fmt}, StringRef()); 141 } 142 143 std::vector<ReplacementItem> 144 formatv_object_base::parseFormatString(StringRef Fmt) { 145 std::vector<ReplacementItem> Replacements; 146 ReplacementItem I; 147 while (!Fmt.empty()) { 148 std::tie(I, Fmt) = splitLiteralAndReplacement(Fmt); 149 if (I.Type != ReplacementType::Empty) 150 Replacements.push_back(I); 151 } 152 return Replacements; 153 } 154 155 void detail::format_adapter::anchor() { } 156