brintos

brintos / llvm-project-archived public Read only

0
0
Text · 30.8 KiB · 95a41ea Raw
1165 lines · cpp
1//===- lib/Support/YAMLTraits.cpp -----------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Support/YAMLTraits.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/SmallString.h"12#include "llvm/ADT/StringExtras.h"13#include "llvm/ADT/StringRef.h"14#include "llvm/ADT/Twine.h"15#include "llvm/Support/Casting.h"16#include "llvm/Support/Errc.h"17#include "llvm/Support/ErrorHandling.h"18#include "llvm/Support/Format.h"19#include "llvm/Support/LineIterator.h"20#include "llvm/Support/MemoryBuffer.h"21#include "llvm/Support/VersionTuple.h"22#include "llvm/Support/YAMLParser.h"23#include "llvm/Support/raw_ostream.h"24#include <cassert>25#include <cstdint>26#include <cstring>27#include <string>28#include <vector>29 30using namespace llvm;31using namespace yaml;32 33//===----------------------------------------------------------------------===//34//  IO35//===----------------------------------------------------------------------===//36 37IO::IO(void *Context) : Ctxt(Context) {}38 39IO::~IO() = default;40 41void *IO::getContext() const {42  return Ctxt;43}44 45void IO::setContext(void *Context) {46  Ctxt = Context;47}48 49void IO::setAllowUnknownKeys(bool Allow) {50  llvm_unreachable("Only supported for Input");51}52 53//===----------------------------------------------------------------------===//54//  Input55//===----------------------------------------------------------------------===//56 57Input::Input(StringRef InputContent, void *Ctxt,58             SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)59    : IO(Ctxt), Strm(new Stream(InputContent, SrcMgr, false, &EC)) {60  if (DiagHandler)61    SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);62  DocIterator = Strm->begin();63}64 65Input::Input(MemoryBufferRef Input, void *Ctxt,66             SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt)67    : IO(Ctxt), Strm(new Stream(Input, SrcMgr, false, &EC)) {68  if (DiagHandler)69    SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);70  DocIterator = Strm->begin();71}72 73Input::~Input() = default;74 75std::error_code Input::error() { return EC; }76 77bool Input::outputting() const {78  return false;79}80 81bool Input::setCurrentDocument() {82  if (DocIterator != Strm->end()) {83    Node *N = DocIterator->getRoot();84    if (!N) {85      EC = make_error_code(errc::invalid_argument);86      return false;87    }88 89    if (isa<NullNode>(N)) {90      // Empty files are allowed and ignored91      ++DocIterator;92      return setCurrentDocument();93    }94    releaseHNodeBuffers();95    TopNode = createHNodes(N);96    CurrentNode = TopNode;97    return true;98  }99  return false;100}101 102bool Input::nextDocument() {103  return ++DocIterator != Strm->end();104}105 106const Node *Input::getCurrentNode() const {107  return CurrentNode ? CurrentNode->_node : nullptr;108}109 110bool Input::mapTag(StringRef Tag, bool Default) {111  // CurrentNode can be null if setCurrentDocument() was unable to112  // parse the document because it was invalid or empty.113  if (!CurrentNode)114    return false;115 116  std::string foundTag = CurrentNode->_node->getVerbatimTag();117  if (foundTag.empty()) {118    // If no tag found and 'Tag' is the default, say it was found.119    return Default;120  }121  // Return true iff found tag matches supplied tag.122  return Tag == foundTag;123}124 125void Input::beginMapping() {126  if (EC)127    return;128  // CurrentNode can be null if the document is empty.129  MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);130  if (MN) {131    MN->ValidKeys.clear();132  }133}134 135std::vector<StringRef> Input::keys() {136  MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);137  std::vector<StringRef> Ret;138  if (!MN) {139    setError(CurrentNode, "not a mapping");140    return Ret;141  }142  for (auto &P : MN->Mapping)143    Ret.push_back(P.first());144  return Ret;145}146 147bool Input::preflightKey(StringRef Key, bool Required, bool, bool &UseDefault,148                         void *&SaveInfo) {149  UseDefault = false;150  if (EC)151    return false;152 153  // CurrentNode is null for empty documents, which is an error in case required154  // nodes are present.155  if (!CurrentNode) {156    if (Required)157      EC = make_error_code(errc::invalid_argument);158    else159      UseDefault = true;160    return false;161  }162 163  MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);164  if (!MN) {165    if (Required || !isa<EmptyHNode>(CurrentNode))166      setError(CurrentNode, "not a mapping");167    else168      UseDefault = true;169    return false;170  }171  MN->ValidKeys.push_back(Key.str());172  HNode *Value = MN->Mapping[Key].first;173  if (!Value) {174    if (Required)175      setError(CurrentNode, Twine("missing required key '") + Key + "'");176    else177      UseDefault = true;178    return false;179  }180  SaveInfo = CurrentNode;181  CurrentNode = Value;182  return true;183}184 185void Input::postflightKey(void *saveInfo) {186  CurrentNode = reinterpret_cast<HNode *>(saveInfo);187}188 189void Input::endMapping() {190  if (EC)191    return;192  // CurrentNode can be null if the document is empty.193  MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);194  if (!MN)195    return;196  for (const auto &NN : MN->Mapping) {197    if (!is_contained(MN->ValidKeys, NN.first())) {198      const SMRange &ReportLoc = NN.second.second;199      if (!AllowUnknownKeys) {200        setError(ReportLoc, Twine("unknown key '") + NN.first() + "'");201        break;202      } else203        reportWarning(ReportLoc, Twine("unknown key '") + NN.first() + "'");204    }205  }206}207 208void Input::beginFlowMapping() { beginMapping(); }209 210void Input::endFlowMapping() { endMapping(); }211 212unsigned Input::beginSequence() {213  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))214    return SQ->Entries.size();215  if (isa<EmptyHNode>(CurrentNode))216    return 0;217  // Treat case where there's a scalar "null" value as an empty sequence.218  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {219    if (isNull(SN->value()))220      return 0;221  }222  // Any other type of HNode is an error.223  setError(CurrentNode, "not a sequence");224  return 0;225}226 227void Input::endSequence() {228}229 230bool Input::preflightElement(unsigned Index, void *&SaveInfo) {231  if (EC)232    return false;233  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {234    SaveInfo = CurrentNode;235    CurrentNode = SQ->Entries[Index];236    return true;237  }238  return false;239}240 241void Input::postflightElement(void *SaveInfo) {242  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);243}244 245unsigned Input::beginFlowSequence() { return beginSequence(); }246 247bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {248  if (EC)249    return false;250  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {251    SaveInfo = CurrentNode;252    CurrentNode = SQ->Entries[index];253    return true;254  }255  return false;256}257 258void Input::postflightFlowElement(void *SaveInfo) {259  CurrentNode = reinterpret_cast<HNode *>(SaveInfo);260}261 262void Input::endFlowSequence() {263}264 265void Input::beginEnumScalar() {266  ScalarMatchFound = false;267}268 269bool Input::matchEnumScalar(StringRef Str, bool) {270  if (ScalarMatchFound)271    return false;272  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {273    if (SN->value() == Str) {274      ScalarMatchFound = true;275      return true;276    }277  }278  return false;279}280 281bool Input::matchEnumFallback() {282  if (ScalarMatchFound)283    return false;284  ScalarMatchFound = true;285  return true;286}287 288void Input::endEnumScalar() {289  if (!ScalarMatchFound) {290    setError(CurrentNode, "unknown enumerated scalar");291  }292}293 294bool Input::beginBitSetScalar(bool &DoClear) {295  BitValuesUsed.clear();296  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {297    BitValuesUsed.resize(SQ->Entries.size());298  } else {299    setError(CurrentNode, "expected sequence of bit values");300  }301  DoClear = true;302  return true;303}304 305bool Input::bitSetMatch(StringRef Str, bool) {306  if (EC)307    return false;308  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {309    unsigned Index = 0;310    for (auto &N : SQ->Entries) {311      if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N)) {312        if (SN->value() == Str) {313          BitValuesUsed[Index] = true;314          return true;315        }316      } else {317        setError(CurrentNode, "unexpected scalar in sequence of bit values");318      }319      ++Index;320    }321  } else {322    setError(CurrentNode, "expected sequence of bit values");323  }324  return false;325}326 327void Input::endBitSetScalar() {328  if (EC)329    return;330  if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {331    assert(BitValuesUsed.size() == SQ->Entries.size());332    for (unsigned i = 0; i < SQ->Entries.size(); ++i) {333      if (!BitValuesUsed[i]) {334        setError(SQ->Entries[i], "unknown bit value");335        return;336      }337    }338  }339}340 341void Input::scalarString(StringRef &S, QuotingType) {342  if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {343    S = SN->value();344  } else {345    setError(CurrentNode, "unexpected scalar");346  }347}348 349void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); }350 351void Input::scalarTag(std::string &Tag) {352  Tag = CurrentNode->_node->getVerbatimTag();353}354 355void Input::setError(HNode *hnode, const Twine &message) {356  assert(hnode && "HNode must not be NULL");357  setError(hnode->_node, message);358}359 360NodeKind Input::getNodeKind() {361  if (isa<ScalarHNode>(CurrentNode))362    return NodeKind::Scalar;363  else if (isa<MapHNode>(CurrentNode))364    return NodeKind::Map;365  else if (isa<SequenceHNode>(CurrentNode))366    return NodeKind::Sequence;367  llvm_unreachable("Unsupported node kind");368}369 370void Input::setError(Node *node, const Twine &message) {371  Strm->printError(node, message);372  EC = make_error_code(errc::invalid_argument);373}374 375void Input::setError(const SMRange &range, const Twine &message) {376  Strm->printError(range, message);377  EC = make_error_code(errc::invalid_argument);378}379 380void Input::reportWarning(HNode *hnode, const Twine &message) {381  assert(hnode && "HNode must not be NULL");382  Strm->printError(hnode->_node, message, SourceMgr::DK_Warning);383}384 385void Input::reportWarning(Node *node, const Twine &message) {386  Strm->printError(node, message, SourceMgr::DK_Warning);387}388 389void Input::reportWarning(const SMRange &range, const Twine &message) {390  Strm->printError(range, message, SourceMgr::DK_Warning);391}392 393void Input::releaseHNodeBuffers() {394  EmptyHNodeAllocator.DestroyAll();395  ScalarHNodeAllocator.DestroyAll();396  SequenceHNodeAllocator.DestroyAll();397  MapHNodeAllocator.DestroyAll();398}399 400Input::HNode *Input::createHNodes(Node *N) {401  SmallString<128> StringStorage;402  switch (N->getType()) {403  case Node::NK_Scalar: {404    ScalarNode *SN = dyn_cast<ScalarNode>(N);405    StringRef KeyStr = SN->getValue(StringStorage);406    if (!StringStorage.empty()) {407      // Copy string to permanent storage408      KeyStr = StringStorage.str().copy(StringAllocator);409    }410    return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, KeyStr);411  }412  case Node::NK_BlockScalar: {413    BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N);414    StringRef ValueCopy = BSN->getValue().copy(StringAllocator);415    return new (ScalarHNodeAllocator.Allocate()) ScalarHNode(N, ValueCopy);416  }417  case Node::NK_Sequence: {418    SequenceNode *SQ = dyn_cast<SequenceNode>(N);419    auto SQHNode = new (SequenceHNodeAllocator.Allocate()) SequenceHNode(N);420    for (Node &SN : *SQ) {421      auto Entry = createHNodes(&SN);422      if (EC)423        break;424      SQHNode->Entries.push_back(Entry);425    }426    return SQHNode;427  }428  case Node::NK_Mapping: {429    MappingNode *Map = dyn_cast<MappingNode>(N);430    auto mapHNode = new (MapHNodeAllocator.Allocate()) MapHNode(N);431    for (KeyValueNode &KVN : *Map) {432      Node *KeyNode = KVN.getKey();433      ScalarNode *Key = dyn_cast_or_null<ScalarNode>(KeyNode);434      Node *Value = KVN.getValue();435      if (!Key || !Value) {436        if (!Key)437          setError(KeyNode, "Map key must be a scalar");438        if (!Value)439          setError(KeyNode, "Map value must not be empty");440        break;441      }442      StringStorage.clear();443      StringRef KeyStr = Key->getValue(StringStorage);444      if (!StringStorage.empty()) {445        // Copy string to permanent storage446        KeyStr = StringStorage.str().copy(StringAllocator);447      }448      if (mapHNode->Mapping.count(KeyStr))449        // From YAML spec: "The content of a mapping node is an unordered set of450        // key/value node pairs, with the restriction that each of the keys is451        // unique."452        setError(KeyNode, Twine("duplicated mapping key '") + KeyStr + "'");453      auto ValueHNode = createHNodes(Value);454      if (EC)455        break;456      mapHNode->Mapping[KeyStr] =457          std::make_pair(std::move(ValueHNode), KeyNode->getSourceRange());458    }459    return std::move(mapHNode);460  }461  case Node::NK_Null:462    return new (EmptyHNodeAllocator.Allocate()) EmptyHNode(N);463  default:464    setError(N, "unknown node kind");465    return nullptr;466  }467}468 469void Input::setError(const Twine &Message) {470  setError(CurrentNode, Message);471}472 473void Input::setAllowUnknownKeys(bool Allow) { AllowUnknownKeys = Allow; }474 475bool Input::canElideEmptySequence() {476  return false;477}478 479//===----------------------------------------------------------------------===//480//  Output481//===----------------------------------------------------------------------===//482 483Output::Output(raw_ostream &yout, void *context, int WrapColumn)484    : IO(context), Out(yout), WrapColumn(WrapColumn) {}485 486Output::~Output() = default;487 488bool Output::outputting() const {489  return true;490}491 492void Output::beginMapping() {493  StateStack.push_back(inMapFirstKey);494  PaddingBeforeContainer = Padding;495  Padding = "\n";496}497 498bool Output::mapTag(StringRef Tag, bool Use) {499  if (Use) {500    // If this tag is being written inside a sequence we should write the start501    // of the sequence before writing the tag, otherwise the tag won't be502    // attached to the element in the sequence, but rather the sequence itself.503    bool SequenceElement = false;504    if (StateStack.size() > 1) {505      auto &E = StateStack[StateStack.size() - 2];506      SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E);507    }508    if (SequenceElement && StateStack.back() == inMapFirstKey) {509      newLineCheck();510    } else {511      output(" ");512    }513    output(Tag);514    if (SequenceElement) {515      // If we're writing the tag during the first element of a map, the tag516      // takes the place of the first element in the sequence.517      if (StateStack.back() == inMapFirstKey) {518        StateStack.pop_back();519        StateStack.push_back(inMapOtherKey);520      }521      // Tags inside maps in sequences should act as keys in the map from a522      // formatting perspective, so we always want a newline in a sequence.523      Padding = "\n";524    }525  }526  return Use;527}528 529void Output::endMapping() {530  // If we did not map anything, we should explicitly emit an empty map531  if (StateStack.back() == inMapFirstKey) {532    Padding = PaddingBeforeContainer;533    newLineCheck();534    output("{}");535    Padding = "\n";536  }537  StateStack.pop_back();538}539 540std::vector<StringRef> Output::keys() {541  report_fatal_error("invalid call");542}543 544bool Output::preflightKey(StringRef Key, bool Required, bool SameAsDefault,545                          bool &UseDefault, void *&SaveInfo) {546  UseDefault = false;547  SaveInfo = nullptr;548  if (Required || !SameAsDefault || WriteDefaultValues) {549    auto State = StateStack.back();550    if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {551      flowKey(Key);552    } else {553      newLineCheck();554      paddedKey(Key);555    }556    return true;557  }558  return false;559}560 561void Output::postflightKey(void *) {562  if (StateStack.back() == inMapFirstKey) {563    StateStack.pop_back();564    StateStack.push_back(inMapOtherKey);565  } else if (StateStack.back() == inFlowMapFirstKey) {566    StateStack.pop_back();567    StateStack.push_back(inFlowMapOtherKey);568  }569}570 571void Output::beginFlowMapping() {572  StateStack.push_back(inFlowMapFirstKey);573  newLineCheck();574  ColumnAtMapFlowStart = Column;575  output("{ ");576}577 578void Output::endFlowMapping() {579  StateStack.pop_back();580  outputUpToEndOfLine(" }");581}582 583void Output::beginDocuments() {584  outputUpToEndOfLine("---");585}586 587bool Output::preflightDocument(unsigned index) {588  if (index > 0)589    outputUpToEndOfLine("\n---");590  return true;591}592 593void Output::postflightDocument() {594}595 596void Output::endDocuments() {597  output("\n...\n");598}599 600unsigned Output::beginSequence() {601  StateStack.push_back(inSeqFirstElement);602  PaddingBeforeContainer = Padding;603  Padding = "\n";604  return 0;605}606 607void Output::endSequence() {608  // If we did not emit anything, we should explicitly emit an empty sequence609  if (StateStack.back() == inSeqFirstElement) {610    Padding = PaddingBeforeContainer;611    newLineCheck(/*EmptySequence=*/true);612    output("[]");613    Padding = "\n";614  }615  StateStack.pop_back();616}617 618bool Output::preflightElement(unsigned, void *&SaveInfo) {619  SaveInfo = nullptr;620  return true;621}622 623void Output::postflightElement(void *) {624  if (StateStack.back() == inSeqFirstElement) {625    StateStack.pop_back();626    StateStack.push_back(inSeqOtherElement);627  } else if (StateStack.back() == inFlowSeqFirstElement) {628    StateStack.pop_back();629    StateStack.push_back(inFlowSeqOtherElement);630  }631}632 633unsigned Output::beginFlowSequence() {634  StateStack.push_back(inFlowSeqFirstElement);635  newLineCheck();636  ColumnAtFlowStart = Column;637  output("[ ");638  NeedFlowSequenceComma = false;639  return 0;640}641 642void Output::endFlowSequence() {643  StateStack.pop_back();644  outputUpToEndOfLine(" ]");645}646 647bool Output::preflightFlowElement(unsigned, void *&SaveInfo) {648  if (NeedFlowSequenceComma)649    output(", ");650  if (WrapColumn && Column > WrapColumn) {651    output("\n");652    for (int i = 0; i < ColumnAtFlowStart; ++i)653      output(" ");654    Column = ColumnAtFlowStart;655    output("  ");656  }657  SaveInfo = nullptr;658  return true;659}660 661void Output::postflightFlowElement(void *) {662  NeedFlowSequenceComma = true;663}664 665void Output::beginEnumScalar() {666  EnumerationMatchFound = false;667}668 669bool Output::matchEnumScalar(StringRef Str, bool Match) {670  if (Match && !EnumerationMatchFound) {671    newLineCheck();672    outputUpToEndOfLine(Str);673    EnumerationMatchFound = true;674  }675  return false;676}677 678bool Output::matchEnumFallback() {679  if (EnumerationMatchFound)680    return false;681  EnumerationMatchFound = true;682  return true;683}684 685void Output::endEnumScalar() {686  if (!EnumerationMatchFound)687    llvm_unreachable("bad runtime enum value");688}689 690bool Output::beginBitSetScalar(bool &DoClear) {691  newLineCheck();692  output("[ ");693  NeedBitValueComma = false;694  DoClear = false;695  return true;696}697 698bool Output::bitSetMatch(StringRef Str, bool Matches) {699  if (Matches) {700    if (NeedBitValueComma)701      output(", ");702    output(Str);703    NeedBitValueComma = true;704  }705  return false;706}707 708void Output::endBitSetScalar() {709  outputUpToEndOfLine(" ]");710}711 712void Output::scalarString(StringRef &S, QuotingType MustQuote) {713  newLineCheck();714  if (S.empty()) {715    // Print '' for the empty string because leaving the field empty is not716    // allowed.717    outputUpToEndOfLine("''");718    return;719  }720  output(S, MustQuote);721  outputUpToEndOfLine("");722}723 724void Output::blockScalarString(StringRef &S) {725  if (!StateStack.empty())726    newLineCheck();727  output(" |");728 729  unsigned Indent = StateStack.empty() ? 1 : StateStack.size();730 731  auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);732  for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {733    outputNewLine();734    for (unsigned I = 0; I < Indent; ++I) {735      output("  ");736    }737    output(*Lines);738  }739  outputUpToEndOfLine("");740}741 742void Output::scalarTag(std::string &Tag) {743  if (Tag.empty())744    return;745  newLineCheck();746  output(Tag);747  output(" ");748}749 750void Output::setError(const Twine &message) {751}752 753std::error_code Output::error() { return {}; }754 755bool Output::canElideEmptySequence() {756  // Normally, with an optional key/value where the value is an empty sequence,757  // the whole key/value can be not written.  But, that produces wrong yaml758  // if the key/value is the only thing in the map and the map is used in759  // a sequence.  This detects if the this sequence is the first key/value760  // in map that itself is embedded in a sequence.761  if (StateStack.size() < 2)762    return true;763  if (StateStack.back() != inMapFirstKey)764    return true;765  return !inSeqAnyElement(StateStack[StateStack.size() - 2]);766}767 768void Output::output(StringRef s) {769  Column += s.size();770  Out << s;771}772 773void Output::output(StringRef S, QuotingType MustQuote) {774  if (MustQuote == QuotingType::None) {775    // Only quote if we must.776    output(S);777    return;778  }779 780  StringLiteral Quote = MustQuote == QuotingType::Single ? StringLiteral("'")781                                                         : StringLiteral("\"");782  output(Quote); // Starting quote.783 784  // When using double-quoted strings (and only in that case), non-printable785  // characters may be present, and will be escaped using a variety of786  // unicode-scalar and special short-form escapes. This is handled in787  // yaml::escape.788  if (MustQuote == QuotingType::Double) {789    output(yaml::escape(S, /* EscapePrintable= */ false));790    output(Quote);791    return;792  }793 794  unsigned i = 0;795  unsigned j = 0;796  unsigned End = S.size();797  const char *Base = S.data();798 799  // When using single-quoted strings, any single quote ' must be doubled to be800  // escaped.801  while (j < End) {802    if (S[j] == '\'') {                   // Escape quotes.803      output(StringRef(&Base[i], j - i)); // "flush".804      output(StringLiteral("''"));        // Print it as ''805      i = j + 1;806    }807    ++j;808  }809  output(StringRef(&Base[i], j - i));810  output(Quote); // Ending quote.811}812 813void Output::outputUpToEndOfLine(StringRef s) {814  output(s);815  if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) &&816                             !inFlowMapAnyKey(StateStack.back())))817    Padding = "\n";818}819 820void Output::outputNewLine() {821  Out << "\n";822  Column = 0;823}824 825// if seq at top, indent as if map, then add "- "826// if seq in middle, use "- " if firstKey, else use "  "827//828 829void Output::newLineCheck(bool EmptySequence) {830  if (Padding != "\n") {831    output(Padding);832    Padding = {};833    return;834  }835  outputNewLine();836  Padding = {};837 838  if (StateStack.size() == 0 || EmptySequence)839    return;840 841  unsigned Indent = StateStack.size() - 1;842  bool PossiblyNestedSeq = false;843  auto I = StateStack.rbegin(), E = StateStack.rend();844 845  if (inSeqAnyElement(*I)) {846    PossiblyNestedSeq = true; // Not possibly but always.847    ++Indent;848  } else if (*I == inMapFirstKey || *I == inFlowMapFirstKey ||849             inFlowSeqAnyElement(*I)) {850    PossiblyNestedSeq = true;851    ++I; // Skip back().852  }853 854  unsigned OutputDashCount = 0;855  if (PossiblyNestedSeq) {856    // Count up consecutive inSeqFirstElement from the end, unless857    // inSeqFirstElement is the top of nested sequence.858    while (I != E) {859      // Don't count the top of nested sequence.860      if (!inSeqAnyElement(*I))861        break;862 863      ++OutputDashCount;864 865      // Stop counting if consecutive inSeqFirstElement ends.866      if (*I++ != inSeqFirstElement)867        break;868    }869  }870 871  for (unsigned I = OutputDashCount; I < Indent; ++I)872    output("  ");873 874  for (unsigned I = 0; I < OutputDashCount; ++I)875    output("- ");876}877 878void Output::paddedKey(StringRef key) {879  output(key, needsQuotes(key, false));880  output(":");881  const char *spaces = "                ";882  if (key.size() < strlen(spaces))883    Padding = &spaces[key.size()];884  else885    Padding = " ";886}887 888void Output::flowKey(StringRef Key) {889  if (StateStack.back() == inFlowMapOtherKey)890    output(", ");891  if (WrapColumn && Column > WrapColumn) {892    output("\n");893    for (int I = 0; I < ColumnAtMapFlowStart; ++I)894      output(" ");895    Column = ColumnAtMapFlowStart;896    output("  ");897  }898  output(Key, needsQuotes(Key, false));899  output(": ");900}901 902NodeKind Output::getNodeKind() { report_fatal_error("invalid call"); }903 904bool Output::inSeqAnyElement(InState State) {905  return State == inSeqFirstElement || State == inSeqOtherElement;906}907 908bool Output::inFlowSeqAnyElement(InState State) {909  return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement;910}911 912bool Output::inMapAnyKey(InState State) {913  return State == inMapFirstKey || State == inMapOtherKey;914}915 916bool Output::inFlowMapAnyKey(InState State) {917  return State == inFlowMapFirstKey || State == inFlowMapOtherKey;918}919 920//===----------------------------------------------------------------------===//921//  traits for built-in types922//===----------------------------------------------------------------------===//923 924void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {925  Out << (Val ? "true" : "false");926}927 928StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {929  if (std::optional<bool> Parsed = parseBool(Scalar)) {930    Val = *Parsed;931    return StringRef();932  }933  return "invalid boolean";934}935 936void ScalarTraits<StringRef>::output(const StringRef &Val, void *,937                                     raw_ostream &Out) {938  Out << Val;939}940 941StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,942                                         StringRef &Val) {943  Val = Scalar;944  return StringRef();945}946 947void ScalarTraits<std::string>::output(const std::string &Val, void *,948                                       raw_ostream &Out) {949  Out << Val;950}951 952StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,953                                           std::string &Val) {954  Val = Scalar.str();955  return StringRef();956}957 958void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,959                                   raw_ostream &Out) {960  // use temp uin32_t because ostream thinks uint8_t is a character961  uint32_t Num = Val;962  Out << Num;963}964 965StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {966  unsigned long long n;967  if (getAsUnsignedInteger(Scalar, 0, n))968    return "invalid number";969  if (n > 0xFF)970    return "out of range number";971  Val = n;972  return StringRef();973}974 975void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,976                                    raw_ostream &Out) {977  Out << Val;978}979 980StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,981                                        uint16_t &Val) {982  unsigned long long n;983  if (getAsUnsignedInteger(Scalar, 0, n))984    return "invalid number";985  if (n > 0xFFFF)986    return "out of range number";987  Val = n;988  return StringRef();989}990 991void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,992                                    raw_ostream &Out) {993  Out << Val;994}995 996StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,997                                        uint32_t &Val) {998  unsigned long long n;999  if (getAsUnsignedInteger(Scalar, 0, n))1000    return "invalid number";1001  if (n > 0xFFFFFFFFUL)1002    return "out of range number";1003  Val = n;1004  return StringRef();1005}1006 1007void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,1008                                    raw_ostream &Out) {1009  Out << Val;1010}1011 1012StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,1013                                        uint64_t &Val) {1014  unsigned long long N;1015  if (getAsUnsignedInteger(Scalar, 0, N))1016    return "invalid number";1017  Val = N;1018  return StringRef();1019}1020 1021void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {1022  // use temp in32_t because ostream thinks int8_t is a character1023  int32_t Num = Val;1024  Out << Num;1025}1026 1027StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {1028  long long N;1029  if (getAsSignedInteger(Scalar, 0, N))1030    return "invalid number";1031  if ((N > 127) || (N < -128))1032    return "out of range number";1033  Val = N;1034  return StringRef();1035}1036 1037void ScalarTraits<int16_t>::output(const int16_t &Val, void *,1038                                   raw_ostream &Out) {1039  Out << Val;1040}1041 1042StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {1043  long long N;1044  if (getAsSignedInteger(Scalar, 0, N))1045    return "invalid number";1046  if ((N > INT16_MAX) || (N < INT16_MIN))1047    return "out of range number";1048  Val = N;1049  return StringRef();1050}1051 1052void ScalarTraits<int32_t>::output(const int32_t &Val, void *,1053                                   raw_ostream &Out) {1054  Out << Val;1055}1056 1057StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {1058  long long N;1059  if (getAsSignedInteger(Scalar, 0, N))1060    return "invalid number";1061  if ((N > INT32_MAX) || (N < INT32_MIN))1062    return "out of range number";1063  Val = N;1064  return StringRef();1065}1066 1067void ScalarTraits<int64_t>::output(const int64_t &Val, void *,1068                                   raw_ostream &Out) {1069  Out << Val;1070}1071 1072StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {1073  long long N;1074  if (getAsSignedInteger(Scalar, 0, N))1075    return "invalid number";1076  Val = N;1077  return StringRef();1078}1079 1080void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {1081  Out << format("%g", Val);1082}1083 1084StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {1085  if (to_float(Scalar, Val))1086    return StringRef();1087  return "invalid floating point number";1088}1089 1090void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {1091  Out << format("%g", Val);1092}1093 1094StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {1095  if (to_float(Scalar, Val))1096    return StringRef();1097  return "invalid floating point number";1098}1099 1100void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {1101  Out << format("0x%" PRIX8, (uint8_t)Val);1102}1103 1104StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {1105  unsigned long long n;1106  if (getAsUnsignedInteger(Scalar, 0, n))1107    return "invalid hex8 number";1108  if (n > 0xFF)1109    return "out of range hex8 number";1110  Val = n;1111  return StringRef();1112}1113 1114void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {1115  Out << format("0x%" PRIX16, (uint16_t)Val);1116}1117 1118StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {1119  unsigned long long n;1120  if (getAsUnsignedInteger(Scalar, 0, n))1121    return "invalid hex16 number";1122  if (n > 0xFFFF)1123    return "out of range hex16 number";1124  Val = n;1125  return StringRef();1126}1127 1128void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {1129  Out << format("0x%" PRIX32, (uint32_t)Val);1130}1131 1132StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {1133  unsigned long long n;1134  if (getAsUnsignedInteger(Scalar, 0, n))1135    return "invalid hex32 number";1136  if (n > 0xFFFFFFFFUL)1137    return "out of range hex32 number";1138  Val = n;1139  return StringRef();1140}1141 1142void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {1143  Out << format("0x%" PRIX64, (uint64_t)Val);1144}1145 1146StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {1147  unsigned long long Num;1148  if (getAsUnsignedInteger(Scalar, 0, Num))1149    return "invalid hex64 number";1150  Val = Num;1151  return StringRef();1152}1153 1154void ScalarTraits<VersionTuple>::output(const VersionTuple &Val, void *,1155                                        llvm::raw_ostream &Out) {1156  Out << Val.getAsString();1157}1158 1159StringRef ScalarTraits<VersionTuple>::input(StringRef Scalar, void *,1160                                            VersionTuple &Val) {1161  if (Val.tryParse(Scalar))1162    return "invalid version format";1163  return StringRef();1164}1165