X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FYAMLTraits.cpp;h=5472e0e1dd49f27a9093b788efb1c66112b827e4;hb=ce30a8106d7d33af9c18518c11e808eaeebc2cce;hp=8fcef40d243f4499364034eb38632cf288b79b8b;hpb=2b45dd58b22da40bb08e82d1564ccecca4a700f5;p=oota-llvm.git diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp index 8fcef40d243..5472e0e1dd4 100644 --- a/lib/Support/YAMLTraits.cpp +++ b/lib/Support/YAMLTraits.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/raw_ostream.h" +#include #include using namespace llvm; using namespace yaml; @@ -40,18 +41,29 @@ void IO::setContext(void *Context) { // Input //===----------------------------------------------------------------------===// -Input::Input(StringRef InputContent, void *Ctxt) : IO(Ctxt), CurrentNode(NULL) { - Strm = new Stream(InputContent, SrcMgr); +Input::Input(StringRef InputContent, + void *Ctxt, + SourceMgr::DiagHandlerTy DiagHandler, + void *DiagHandlerCtxt) + : IO(Ctxt), + Strm(new Stream(InputContent, SrcMgr)), + CurrentNode(NULL) { + if (DiagHandler) + SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt); DocIterator = Strm->begin(); } +Input::~Input() { +} + error_code Input::error() { return EC; } -void Input::setDiagHandler(SourceMgr::DiagHandlerTy Handler, void *Ctxt) { - SrcMgr.setDiagHandler(Handler, Ctxt); -} +// Pin the vtables to this file. +void Input::HNode::anchor() {} +void Input::EmptyHNode::anchor() {} +void Input::ScalarHNode::anchor() {} bool Input::outputting() { return false; @@ -60,12 +72,19 @@ bool Input::outputting() { bool Input::setCurrentDocument() { if (DocIterator != Strm->end()) { Node *N = DocIterator->getRoot(); + if (!N) { + assert(Strm->failed() && "Root is NULL iff parsing failed"); + EC = make_error_code(errc::invalid_argument); + return false; + } + if (isa(N)) { // Empty files are allowed and ignored ++DocIterator; return setCurrentDocument(); } - CurrentNode = this->createHNodes(N); + TopNode.reset(this->createHNodes(N)); + CurrentNode = TopNode.get(); return true; } return false; @@ -75,10 +94,21 @@ void Input::nextDocument() { ++DocIterator; } +bool Input::mapTag(StringRef Tag, bool Default) { + std::string foundTag = CurrentNode->_node->getVerbatimTag(); + if (foundTag.empty()) { + // If no tag found and 'Tag' is the default, say it was found. + return Default; + } + // Return true iff found tag matches supplied tag. + return Tag.equals(foundTag); +} + void Input::beginMapping() { if (EC) return; - MapHNode *MN = dyn_cast(CurrentNode); + // CurrentNode can be null if the document is empty. + MapHNode *MN = dyn_cast_or_null(CurrentNode); if (MN) { MN->ValidKeys.clear(); } @@ -89,6 +119,15 @@ bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault, UseDefault = false; if (EC) return false; + + // CurrentNode is null for empty documents, which is an error in case required + // nodes are present. + if (!CurrentNode) { + if (Required) + EC = make_error_code(errc::invalid_argument); + return false; + } + MapHNode *MN = dyn_cast(CurrentNode); if (!MN) { setError(CurrentNode, "not a mapping"); @@ -115,13 +154,14 @@ void Input::postflightKey(void *saveInfo) { void Input::endMapping() { if (EC) return; - MapHNode *MN = dyn_cast(CurrentNode); + // CurrentNode can be null if the document is empty. + MapHNode *MN = dyn_cast_or_null(CurrentNode); if (!MN) return; for (MapHNode::NameToNode::iterator i = MN->Mapping.begin(), End = MN->Mapping.end(); i != End; ++i) { - if (!MN->isValidKey(i->first)) { - setError(i->second, Twine("unknown key '") + i->first + "'"); + if (!MN->isValidKey(i->first())) { + setError(i->second, Twine("unknown key '") + i->first() + "'"); break; } } @@ -256,6 +296,7 @@ void Input::scalarString(StringRef &S) { } void Input::setError(HNode *hnode, const Twine &message) { + assert(hnode && "HNode must not be NULL"); this->setError(hnode->_node, message); } @@ -271,13 +312,13 @@ Input::HNode *Input::createHNodes(Node *N) { if (!StringStorage.empty()) { // Copy string to permanent storage unsigned Len = StringStorage.size(); - char *Buf = Allocator.Allocate(Len); + char *Buf = StringAllocator.Allocate(Len); memcpy(Buf, &StringStorage[0], Len); KeyStr = StringRef(Buf, Len); } - return new (Allocator) ScalarHNode(N, KeyStr); + return new ScalarHNode(N, KeyStr); } else if (SequenceNode *SQ = dyn_cast(N)) { - SequenceHNode *SQHNode = new (Allocator) SequenceHNode(N); + SequenceHNode *SQHNode = new SequenceHNode(N); for (SequenceNode::iterator i = SQ->begin(), End = SQ->end(); i != End; ++i) { HNode *Entry = this->createHNodes(i); @@ -287,7 +328,7 @@ Input::HNode *Input::createHNodes(Node *N) { } return SQHNode; } else if (MappingNode *Map = dyn_cast(N)) { - MapHNode *mapHNode = new (Allocator) MapHNode(N); + MapHNode *mapHNode = new MapHNode(N); for (MappingNode::iterator i = Map->begin(), End = Map->end(); i != End; ++i) { ScalarNode *KeyScalar = dyn_cast(i->getKey()); @@ -296,7 +337,7 @@ Input::HNode *Input::createHNodes(Node *N) { if (!StringStorage.empty()) { // Copy string to permanent storage unsigned Len = StringStorage.size(); - char *Buf = Allocator.Allocate(Len); + char *Buf = StringAllocator.Allocate(Len); memcpy(Buf, &StringStorage[0], Len); KeyStr = StringRef(Buf, Len); } @@ -307,7 +348,7 @@ Input::HNode *Input::createHNodes(Node *N) { } return mapHNode; } else if (isa(N)) { - return new (Allocator) EmptyHNode(N); + return new EmptyHNode(N); } else { setError(N, "unknown node kind"); return NULL; @@ -315,7 +356,7 @@ Input::HNode *Input::createHNodes(Node *N) { } bool Input::MapHNode::isValidKey(StringRef Key) { - for (SmallVector::iterator i = ValidKeys.begin(), + for (SmallVectorImpl::iterator i = ValidKeys.begin(), End = ValidKeys.end(); i != End; ++i) { if (Key.equals(*i)) return true; @@ -327,6 +368,26 @@ void Input::setError(const Twine &Message) { this->setError(CurrentNode, Message); } +bool Input::canElideEmptySequence() { + return false; +} + +Input::MapHNode::~MapHNode() { + for (MapHNode::NameToNode::iterator i = Mapping.begin(), End = Mapping.end(); + i != End; ++i) { + delete i->second; + } +} + +Input::SequenceHNode::~SequenceHNode() { + for (std::vector::iterator i = Entries.begin(), End = Entries.end(); + i != End; ++i) { + delete *i; + } +} + + + //===----------------------------------------------------------------------===// // Output //===----------------------------------------------------------------------===// @@ -354,6 +415,14 @@ void Output::beginMapping() { NeedsNewLine = true; } +bool Output::mapTag(StringRef Tag, bool Use) { + if (Use) { + this->output(" "); + this->output(Tag); + } + return Use; +} + void Output::endMapping() { StateStack.pop_back(); } @@ -411,8 +480,8 @@ void Output::postflightElement(void *) { } unsigned Output::beginFlowSequence() { - this->newLineCheck(); StateStack.push_back(inFlowSeq); + this->newLineCheck(); ColumnAtFlowStart = Column; output("[ "); NeedFlowSequenceComma = false; @@ -482,9 +551,20 @@ void Output::endBitSetScalar() { } void Output::scalarString(StringRef &S) { + const char ScalarSafeChars[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t"; + this->newLineCheck(); - if (S.find('\n') == StringRef::npos) { - // No embedded new-line chars, just print string. + if (S.empty()) { + // Print '' for the empty string because leaving the field empty is not + // allowed. + this->outputUpToEndOfLine("''"); + return; + } + if (S.find_first_not_of(ScalarSafeChars) == StringRef::npos && + !isspace(S.front()) && !isspace(S.back())) { + // If the string consists only of safe characters, print it out without + // quotes. this->outputUpToEndOfLine(S); return; } @@ -509,6 +589,19 @@ void Output::scalarString(StringRef &S) { void Output::setError(const Twine &message) { } +bool Output::canElideEmptySequence() { + // Normally, with an optional key/value where the value is an empty sequence, + // the whole key/value can be not written. But, that produces wrong yaml + // if the key/value is the only thing in the map and the map is used in + // a sequence. This detects if the this sequence is the first key/value + // in map that itself is embedded in a sequnce. + if (StateStack.size() < 2) + return true; + if (StateStack.back() != inMapFirstKey) + return true; + return (StateStack[StateStack.size()-2] != inSeq); +} + void Output::output(StringRef s) { Column += s.size(); Out << s; @@ -596,6 +689,17 @@ StringRef ScalarTraits::input(StringRef Scalar, void *, Val = Scalar; return StringRef(); } + +void ScalarTraits::output(const std::string &Val, void *, + raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits::input(StringRef Scalar, void *, + std::string &Val) { + Val = Scalar.str(); + return StringRef(); +} void ScalarTraits::output(const uint8_t &Val, void *, raw_ostream &Out) {