1 //===- lib/Support/YAMLTraits.cpp -----------------------------------------===//
2 //
3 // The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Support/YAMLTraits.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/Support/Casting.h"
14 #include "llvm/Support/Errc.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/Format.h"
17 #include "llvm/Support/LineIterator.h"
18 #include "llvm/Support/YAMLParser.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <cctype>
21 #include <cstring>
22 using namespace llvm;
23 using namespace yaml;
24
25 //===----------------------------------------------------------------------===//
26 // IO
27 //===----------------------------------------------------------------------===//
28
IO(void * Context)29 IO::IO(void *Context) : Ctxt(Context) {
30 }
31
~IO()32 IO::~IO() {
33 }
34
getContext()35 void *IO::getContext() {
36 return Ctxt;
37 }
38
setContext(void * Context)39 void IO::setContext(void *Context) {
40 Ctxt = Context;
41 }
42
43 //===----------------------------------------------------------------------===//
44 // Input
45 //===----------------------------------------------------------------------===//
46
Input(StringRef InputContent,void * Ctxt,SourceMgr::DiagHandlerTy DiagHandler,void * DiagHandlerCtxt)47 Input::Input(StringRef InputContent,
48 void *Ctxt,
49 SourceMgr::DiagHandlerTy DiagHandler,
50 void *DiagHandlerCtxt)
51 : IO(Ctxt),
52 Strm(new Stream(InputContent, SrcMgr)),
53 CurrentNode(nullptr) {
54 if (DiagHandler)
55 SrcMgr.setDiagHandler(DiagHandler, DiagHandlerCtxt);
56 DocIterator = Strm->begin();
57 }
58
~Input()59 Input::~Input() {
60 }
61
error()62 std::error_code Input::error() { return EC; }
63
64 // Pin the vtables to this file.
anchor()65 void Input::HNode::anchor() {}
anchor()66 void Input::EmptyHNode::anchor() {}
anchor()67 void Input::ScalarHNode::anchor() {}
anchor()68 void Input::MapHNode::anchor() {}
anchor()69 void Input::SequenceHNode::anchor() {}
70
outputting()71 bool Input::outputting() {
72 return false;
73 }
74
setCurrentDocument()75 bool Input::setCurrentDocument() {
76 if (DocIterator != Strm->end()) {
77 Node *N = DocIterator->getRoot();
78 if (!N) {
79 assert(Strm->failed() && "Root is NULL iff parsing failed");
80 EC = make_error_code(errc::invalid_argument);
81 return false;
82 }
83
84 if (isa<NullNode>(N)) {
85 // Empty files are allowed and ignored
86 ++DocIterator;
87 return setCurrentDocument();
88 }
89 TopNode = this->createHNodes(N);
90 CurrentNode = TopNode.get();
91 return true;
92 }
93 return false;
94 }
95
nextDocument()96 bool Input::nextDocument() {
97 return ++DocIterator != Strm->end();
98 }
99
getCurrentNode() const100 const Node *Input::getCurrentNode() const {
101 return CurrentNode ? CurrentNode->_node : nullptr;
102 }
103
mapTag(StringRef Tag,bool Default)104 bool Input::mapTag(StringRef Tag, bool Default) {
105 std::string foundTag = CurrentNode->_node->getVerbatimTag();
106 if (foundTag.empty()) {
107 // If no tag found and 'Tag' is the default, say it was found.
108 return Default;
109 }
110 // Return true iff found tag matches supplied tag.
111 return Tag.equals(foundTag);
112 }
113
beginMapping()114 void Input::beginMapping() {
115 if (EC)
116 return;
117 // CurrentNode can be null if the document is empty.
118 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
119 if (MN) {
120 MN->ValidKeys.clear();
121 }
122 }
123
preflightKey(const char * Key,bool Required,bool,bool & UseDefault,void * & SaveInfo)124 bool Input::preflightKey(const char *Key, bool Required, bool, bool &UseDefault,
125 void *&SaveInfo) {
126 UseDefault = false;
127 if (EC)
128 return false;
129
130 // CurrentNode is null for empty documents, which is an error in case required
131 // nodes are present.
132 if (!CurrentNode) {
133 if (Required)
134 EC = make_error_code(errc::invalid_argument);
135 return false;
136 }
137
138 MapHNode *MN = dyn_cast<MapHNode>(CurrentNode);
139 if (!MN) {
140 setError(CurrentNode, "not a mapping");
141 return false;
142 }
143 MN->ValidKeys.push_back(Key);
144 HNode *Value = MN->Mapping[Key].get();
145 if (!Value) {
146 if (Required)
147 setError(CurrentNode, Twine("missing required key '") + Key + "'");
148 else
149 UseDefault = true;
150 return false;
151 }
152 SaveInfo = CurrentNode;
153 CurrentNode = Value;
154 return true;
155 }
156
postflightKey(void * saveInfo)157 void Input::postflightKey(void *saveInfo) {
158 CurrentNode = reinterpret_cast<HNode *>(saveInfo);
159 }
160
endMapping()161 void Input::endMapping() {
162 if (EC)
163 return;
164 // CurrentNode can be null if the document is empty.
165 MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode);
166 if (!MN)
167 return;
168 for (const auto &NN : MN->Mapping) {
169 if (!MN->isValidKey(NN.first())) {
170 setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'");
171 break;
172 }
173 }
174 }
175
beginFlowMapping()176 void Input::beginFlowMapping() { beginMapping(); }
177
endFlowMapping()178 void Input::endFlowMapping() { endMapping(); }
179
beginSequence()180 unsigned Input::beginSequence() {
181 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode))
182 return SQ->Entries.size();
183 if (isa<EmptyHNode>(CurrentNode))
184 return 0;
185 // Treat case where there's a scalar "null" value as an empty sequence.
186 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
187 if (isNull(SN->value()))
188 return 0;
189 }
190 // Any other type of HNode is an error.
191 setError(CurrentNode, "not a sequence");
192 return 0;
193 }
194
endSequence()195 void Input::endSequence() {
196 }
197
preflightElement(unsigned Index,void * & SaveInfo)198 bool Input::preflightElement(unsigned Index, void *&SaveInfo) {
199 if (EC)
200 return false;
201 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
202 SaveInfo = CurrentNode;
203 CurrentNode = SQ->Entries[Index].get();
204 return true;
205 }
206 return false;
207 }
208
postflightElement(void * SaveInfo)209 void Input::postflightElement(void *SaveInfo) {
210 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
211 }
212
beginFlowSequence()213 unsigned Input::beginFlowSequence() { return beginSequence(); }
214
preflightFlowElement(unsigned index,void * & SaveInfo)215 bool Input::preflightFlowElement(unsigned index, void *&SaveInfo) {
216 if (EC)
217 return false;
218 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
219 SaveInfo = CurrentNode;
220 CurrentNode = SQ->Entries[index].get();
221 return true;
222 }
223 return false;
224 }
225
postflightFlowElement(void * SaveInfo)226 void Input::postflightFlowElement(void *SaveInfo) {
227 CurrentNode = reinterpret_cast<HNode *>(SaveInfo);
228 }
229
endFlowSequence()230 void Input::endFlowSequence() {
231 }
232
beginEnumScalar()233 void Input::beginEnumScalar() {
234 ScalarMatchFound = false;
235 }
236
matchEnumScalar(const char * Str,bool)237 bool Input::matchEnumScalar(const char *Str, bool) {
238 if (ScalarMatchFound)
239 return false;
240 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
241 if (SN->value().equals(Str)) {
242 ScalarMatchFound = true;
243 return true;
244 }
245 }
246 return false;
247 }
248
matchEnumFallback()249 bool Input::matchEnumFallback() {
250 if (ScalarMatchFound)
251 return false;
252 ScalarMatchFound = true;
253 return true;
254 }
255
endEnumScalar()256 void Input::endEnumScalar() {
257 if (!ScalarMatchFound) {
258 setError(CurrentNode, "unknown enumerated scalar");
259 }
260 }
261
beginBitSetScalar(bool & DoClear)262 bool Input::beginBitSetScalar(bool &DoClear) {
263 BitValuesUsed.clear();
264 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
265 BitValuesUsed.insert(BitValuesUsed.begin(), SQ->Entries.size(), false);
266 } else {
267 setError(CurrentNode, "expected sequence of bit values");
268 }
269 DoClear = true;
270 return true;
271 }
272
bitSetMatch(const char * Str,bool)273 bool Input::bitSetMatch(const char *Str, bool) {
274 if (EC)
275 return false;
276 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
277 unsigned Index = 0;
278 for (auto &N : SQ->Entries) {
279 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(N.get())) {
280 if (SN->value().equals(Str)) {
281 BitValuesUsed[Index] = true;
282 return true;
283 }
284 } else {
285 setError(CurrentNode, "unexpected scalar in sequence of bit values");
286 }
287 ++Index;
288 }
289 } else {
290 setError(CurrentNode, "expected sequence of bit values");
291 }
292 return false;
293 }
294
endBitSetScalar()295 void Input::endBitSetScalar() {
296 if (EC)
297 return;
298 if (SequenceHNode *SQ = dyn_cast<SequenceHNode>(CurrentNode)) {
299 assert(BitValuesUsed.size() == SQ->Entries.size());
300 for (unsigned i = 0; i < SQ->Entries.size(); ++i) {
301 if (!BitValuesUsed[i]) {
302 setError(SQ->Entries[i].get(), "unknown bit value");
303 return;
304 }
305 }
306 }
307 }
308
scalarString(StringRef & S,bool)309 void Input::scalarString(StringRef &S, bool) {
310 if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
311 S = SN->value();
312 } else {
313 setError(CurrentNode, "unexpected scalar");
314 }
315 }
316
blockScalarString(StringRef & S)317 void Input::blockScalarString(StringRef &S) { scalarString(S, false); }
318
setError(HNode * hnode,const Twine & message)319 void Input::setError(HNode *hnode, const Twine &message) {
320 assert(hnode && "HNode must not be NULL");
321 this->setError(hnode->_node, message);
322 }
323
setError(Node * node,const Twine & message)324 void Input::setError(Node *node, const Twine &message) {
325 Strm->printError(node, message);
326 EC = make_error_code(errc::invalid_argument);
327 }
328
createHNodes(Node * N)329 std::unique_ptr<Input::HNode> Input::createHNodes(Node *N) {
330 SmallString<128> StringStorage;
331 if (ScalarNode *SN = dyn_cast<ScalarNode>(N)) {
332 StringRef KeyStr = SN->getValue(StringStorage);
333 if (!StringStorage.empty()) {
334 // Copy string to permanent storage
335 KeyStr = StringStorage.str().copy(StringAllocator);
336 }
337 return llvm::make_unique<ScalarHNode>(N, KeyStr);
338 } else if (BlockScalarNode *BSN = dyn_cast<BlockScalarNode>(N)) {
339 StringRef ValueCopy = BSN->getValue().copy(StringAllocator);
340 return llvm::make_unique<ScalarHNode>(N, ValueCopy);
341 } else if (SequenceNode *SQ = dyn_cast<SequenceNode>(N)) {
342 auto SQHNode = llvm::make_unique<SequenceHNode>(N);
343 for (Node &SN : *SQ) {
344 auto Entry = this->createHNodes(&SN);
345 if (EC)
346 break;
347 SQHNode->Entries.push_back(std::move(Entry));
348 }
349 return std::move(SQHNode);
350 } else if (MappingNode *Map = dyn_cast<MappingNode>(N)) {
351 auto mapHNode = llvm::make_unique<MapHNode>(N);
352 for (KeyValueNode &KVN : *Map) {
353 Node *KeyNode = KVN.getKey();
354 ScalarNode *KeyScalar = dyn_cast<ScalarNode>(KeyNode);
355 if (!KeyScalar) {
356 setError(KeyNode, "Map key must be a scalar");
357 break;
358 }
359 StringStorage.clear();
360 StringRef KeyStr = KeyScalar->getValue(StringStorage);
361 if (!StringStorage.empty()) {
362 // Copy string to permanent storage
363 KeyStr = StringStorage.str().copy(StringAllocator);
364 }
365 auto ValueHNode = this->createHNodes(KVN.getValue());
366 if (EC)
367 break;
368 mapHNode->Mapping[KeyStr] = std::move(ValueHNode);
369 }
370 return std::move(mapHNode);
371 } else if (isa<NullNode>(N)) {
372 return llvm::make_unique<EmptyHNode>(N);
373 } else {
374 setError(N, "unknown node kind");
375 return nullptr;
376 }
377 }
378
isValidKey(StringRef Key)379 bool Input::MapHNode::isValidKey(StringRef Key) {
380 for (const char *K : ValidKeys) {
381 if (Key.equals(K))
382 return true;
383 }
384 return false;
385 }
386
setError(const Twine & Message)387 void Input::setError(const Twine &Message) {
388 this->setError(CurrentNode, Message);
389 }
390
canElideEmptySequence()391 bool Input::canElideEmptySequence() {
392 return false;
393 }
394
395 //===----------------------------------------------------------------------===//
396 // Output
397 //===----------------------------------------------------------------------===//
398
Output(raw_ostream & yout,void * context,int WrapColumn)399 Output::Output(raw_ostream &yout, void *context, int WrapColumn)
400 : IO(context),
401 Out(yout),
402 WrapColumn(WrapColumn),
403 Column(0),
404 ColumnAtFlowStart(0),
405 ColumnAtMapFlowStart(0),
406 NeedBitValueComma(false),
407 NeedFlowSequenceComma(false),
408 EnumerationMatchFound(false),
409 NeedsNewLine(false) {
410 }
411
~Output()412 Output::~Output() {
413 }
414
outputting()415 bool Output::outputting() {
416 return true;
417 }
418
beginMapping()419 void Output::beginMapping() {
420 StateStack.push_back(inMapFirstKey);
421 NeedsNewLine = true;
422 }
423
mapTag(StringRef Tag,bool Use)424 bool Output::mapTag(StringRef Tag, bool Use) {
425 if (Use) {
426 // If this tag is being written inside a sequence we should write the start
427 // of the sequence before writing the tag, otherwise the tag won't be
428 // attached to the element in the sequence, but rather the sequence itself.
429 bool SequenceElement =
430 StateStack.size() > 1 && (StateStack[StateStack.size() - 2] == inSeq ||
431 StateStack[StateStack.size() - 2] == inFlowSeq);
432 if (SequenceElement && StateStack.back() == inMapFirstKey) {
433 this->newLineCheck();
434 } else {
435 this->output(" ");
436 }
437 this->output(Tag);
438 if (SequenceElement) {
439 // If we're writing the tag during the first element of a map, the tag
440 // takes the place of the first element in the sequence.
441 if (StateStack.back() == inMapFirstKey) {
442 StateStack.pop_back();
443 StateStack.push_back(inMapOtherKey);
444 }
445 // Tags inside maps in sequences should act as keys in the map from a
446 // formatting perspective, so we always want a newline in a sequence.
447 NeedsNewLine = true;
448 }
449 }
450 return Use;
451 }
452
endMapping()453 void Output::endMapping() {
454 StateStack.pop_back();
455 }
456
preflightKey(const char * Key,bool Required,bool SameAsDefault,bool & UseDefault,void * &)457 bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
458 bool &UseDefault, void *&) {
459 UseDefault = false;
460 if (Required || !SameAsDefault) {
461 auto State = StateStack.back();
462 if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
463 flowKey(Key);
464 } else {
465 this->newLineCheck();
466 this->paddedKey(Key);
467 }
468 return true;
469 }
470 return false;
471 }
472
postflightKey(void *)473 void Output::postflightKey(void *) {
474 if (StateStack.back() == inMapFirstKey) {
475 StateStack.pop_back();
476 StateStack.push_back(inMapOtherKey);
477 } else if (StateStack.back() == inFlowMapFirstKey) {
478 StateStack.pop_back();
479 StateStack.push_back(inFlowMapOtherKey);
480 }
481 }
482
beginFlowMapping()483 void Output::beginFlowMapping() {
484 StateStack.push_back(inFlowMapFirstKey);
485 this->newLineCheck();
486 ColumnAtMapFlowStart = Column;
487 output("{ ");
488 }
489
endFlowMapping()490 void Output::endFlowMapping() {
491 StateStack.pop_back();
492 this->outputUpToEndOfLine(" }");
493 }
494
beginDocuments()495 void Output::beginDocuments() {
496 this->outputUpToEndOfLine("---");
497 }
498
preflightDocument(unsigned index)499 bool Output::preflightDocument(unsigned index) {
500 if (index > 0)
501 this->outputUpToEndOfLine("\n---");
502 return true;
503 }
504
postflightDocument()505 void Output::postflightDocument() {
506 }
507
endDocuments()508 void Output::endDocuments() {
509 output("\n...\n");
510 }
511
beginSequence()512 unsigned Output::beginSequence() {
513 StateStack.push_back(inSeq);
514 NeedsNewLine = true;
515 return 0;
516 }
517
endSequence()518 void Output::endSequence() {
519 StateStack.pop_back();
520 }
521
preflightElement(unsigned,void * &)522 bool Output::preflightElement(unsigned, void *&) {
523 return true;
524 }
525
postflightElement(void *)526 void Output::postflightElement(void *) {
527 }
528
beginFlowSequence()529 unsigned Output::beginFlowSequence() {
530 StateStack.push_back(inFlowSeq);
531 this->newLineCheck();
532 ColumnAtFlowStart = Column;
533 output("[ ");
534 NeedFlowSequenceComma = false;
535 return 0;
536 }
537
endFlowSequence()538 void Output::endFlowSequence() {
539 StateStack.pop_back();
540 this->outputUpToEndOfLine(" ]");
541 }
542
preflightFlowElement(unsigned,void * &)543 bool Output::preflightFlowElement(unsigned, void *&) {
544 if (NeedFlowSequenceComma)
545 output(", ");
546 if (WrapColumn && Column > WrapColumn) {
547 output("\n");
548 for (int i = 0; i < ColumnAtFlowStart; ++i)
549 output(" ");
550 Column = ColumnAtFlowStart;
551 output(" ");
552 }
553 return true;
554 }
555
postflightFlowElement(void *)556 void Output::postflightFlowElement(void *) {
557 NeedFlowSequenceComma = true;
558 }
559
beginEnumScalar()560 void Output::beginEnumScalar() {
561 EnumerationMatchFound = false;
562 }
563
matchEnumScalar(const char * Str,bool Match)564 bool Output::matchEnumScalar(const char *Str, bool Match) {
565 if (Match && !EnumerationMatchFound) {
566 this->newLineCheck();
567 this->outputUpToEndOfLine(Str);
568 EnumerationMatchFound = true;
569 }
570 return false;
571 }
572
matchEnumFallback()573 bool Output::matchEnumFallback() {
574 if (EnumerationMatchFound)
575 return false;
576 EnumerationMatchFound = true;
577 return true;
578 }
579
endEnumScalar()580 void Output::endEnumScalar() {
581 if (!EnumerationMatchFound)
582 llvm_unreachable("bad runtime enum value");
583 }
584
beginBitSetScalar(bool & DoClear)585 bool Output::beginBitSetScalar(bool &DoClear) {
586 this->newLineCheck();
587 output("[ ");
588 NeedBitValueComma = false;
589 DoClear = false;
590 return true;
591 }
592
bitSetMatch(const char * Str,bool Matches)593 bool Output::bitSetMatch(const char *Str, bool Matches) {
594 if (Matches) {
595 if (NeedBitValueComma)
596 output(", ");
597 this->output(Str);
598 NeedBitValueComma = true;
599 }
600 return false;
601 }
602
endBitSetScalar()603 void Output::endBitSetScalar() {
604 this->outputUpToEndOfLine(" ]");
605 }
606
scalarString(StringRef & S,bool MustQuote)607 void Output::scalarString(StringRef &S, bool MustQuote) {
608 this->newLineCheck();
609 if (S.empty()) {
610 // Print '' for the empty string because leaving the field empty is not
611 // allowed.
612 this->outputUpToEndOfLine("''");
613 return;
614 }
615 if (!MustQuote) {
616 // Only quote if we must.
617 this->outputUpToEndOfLine(S);
618 return;
619 }
620 unsigned i = 0;
621 unsigned j = 0;
622 unsigned End = S.size();
623 output("'"); // Starting single quote.
624 const char *Base = S.data();
625 while (j < End) {
626 // Escape a single quote by doubling it.
627 if (S[j] == '\'') {
628 output(StringRef(&Base[i], j - i + 1));
629 output("'");
630 i = j + 1;
631 }
632 ++j;
633 }
634 output(StringRef(&Base[i], j - i));
635 this->outputUpToEndOfLine("'"); // Ending single quote.
636 }
637
blockScalarString(StringRef & S)638 void Output::blockScalarString(StringRef &S) {
639 if (!StateStack.empty())
640 newLineCheck();
641 output(" |");
642 outputNewLine();
643
644 unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
645
646 auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
647 for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
648 for (unsigned I = 0; I < Indent; ++I) {
649 output(" ");
650 }
651 output(*Lines);
652 outputNewLine();
653 }
654 }
655
setError(const Twine & message)656 void Output::setError(const Twine &message) {
657 }
658
canElideEmptySequence()659 bool Output::canElideEmptySequence() {
660 // Normally, with an optional key/value where the value is an empty sequence,
661 // the whole key/value can be not written. But, that produces wrong yaml
662 // if the key/value is the only thing in the map and the map is used in
663 // a sequence. This detects if the this sequence is the first key/value
664 // in map that itself is embedded in a sequnce.
665 if (StateStack.size() < 2)
666 return true;
667 if (StateStack.back() != inMapFirstKey)
668 return true;
669 return (StateStack[StateStack.size()-2] != inSeq);
670 }
671
output(StringRef s)672 void Output::output(StringRef s) {
673 Column += s.size();
674 Out << s;
675 }
676
outputUpToEndOfLine(StringRef s)677 void Output::outputUpToEndOfLine(StringRef s) {
678 this->output(s);
679 if (StateStack.empty() || (StateStack.back() != inFlowSeq &&
680 StateStack.back() != inFlowMapFirstKey &&
681 StateStack.back() != inFlowMapOtherKey))
682 NeedsNewLine = true;
683 }
684
outputNewLine()685 void Output::outputNewLine() {
686 Out << "\n";
687 Column = 0;
688 }
689
690 // if seq at top, indent as if map, then add "- "
691 // if seq in middle, use "- " if firstKey, else use " "
692 //
693
newLineCheck()694 void Output::newLineCheck() {
695 if (!NeedsNewLine)
696 return;
697 NeedsNewLine = false;
698
699 this->outputNewLine();
700
701 assert(StateStack.size() > 0);
702 unsigned Indent = StateStack.size() - 1;
703 bool OutputDash = false;
704
705 if (StateStack.back() == inSeq) {
706 OutputDash = true;
707 } else if ((StateStack.size() > 1) && ((StateStack.back() == inMapFirstKey) ||
708 (StateStack.back() == inFlowSeq) ||
709 (StateStack.back() == inFlowMapFirstKey)) &&
710 (StateStack[StateStack.size() - 2] == inSeq)) {
711 --Indent;
712 OutputDash = true;
713 }
714
715 for (unsigned i = 0; i < Indent; ++i) {
716 output(" ");
717 }
718 if (OutputDash) {
719 output("- ");
720 }
721
722 }
723
paddedKey(StringRef key)724 void Output::paddedKey(StringRef key) {
725 output(key);
726 output(":");
727 const char *spaces = " ";
728 if (key.size() < strlen(spaces))
729 output(&spaces[key.size()]);
730 else
731 output(" ");
732 }
733
flowKey(StringRef Key)734 void Output::flowKey(StringRef Key) {
735 if (StateStack.back() == inFlowMapOtherKey)
736 output(", ");
737 if (WrapColumn && Column > WrapColumn) {
738 output("\n");
739 for (int I = 0; I < ColumnAtMapFlowStart; ++I)
740 output(" ");
741 Column = ColumnAtMapFlowStart;
742 output(" ");
743 }
744 output(Key);
745 output(": ");
746 }
747
748 //===----------------------------------------------------------------------===//
749 // traits for built-in types
750 //===----------------------------------------------------------------------===//
751
output(const bool & Val,void *,raw_ostream & Out)752 void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
753 Out << (Val ? "true" : "false");
754 }
755
input(StringRef Scalar,void *,bool & Val)756 StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
757 if (Scalar.equals("true")) {
758 Val = true;
759 return StringRef();
760 } else if (Scalar.equals("false")) {
761 Val = false;
762 return StringRef();
763 }
764 return "invalid boolean";
765 }
766
output(const StringRef & Val,void *,raw_ostream & Out)767 void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
768 raw_ostream &Out) {
769 Out << Val;
770 }
771
input(StringRef Scalar,void *,StringRef & Val)772 StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
773 StringRef &Val) {
774 Val = Scalar;
775 return StringRef();
776 }
777
output(const std::string & Val,void *,raw_ostream & Out)778 void ScalarTraits<std::string>::output(const std::string &Val, void *,
779 raw_ostream &Out) {
780 Out << Val;
781 }
782
input(StringRef Scalar,void *,std::string & Val)783 StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
784 std::string &Val) {
785 Val = Scalar.str();
786 return StringRef();
787 }
788
output(const uint8_t & Val,void *,raw_ostream & Out)789 void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
790 raw_ostream &Out) {
791 // use temp uin32_t because ostream thinks uint8_t is a character
792 uint32_t Num = Val;
793 Out << Num;
794 }
795
input(StringRef Scalar,void *,uint8_t & Val)796 StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
797 unsigned long long n;
798 if (getAsUnsignedInteger(Scalar, 0, n))
799 return "invalid number";
800 if (n > 0xFF)
801 return "out of range number";
802 Val = n;
803 return StringRef();
804 }
805
output(const uint16_t & Val,void *,raw_ostream & Out)806 void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
807 raw_ostream &Out) {
808 Out << Val;
809 }
810
input(StringRef Scalar,void *,uint16_t & Val)811 StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
812 uint16_t &Val) {
813 unsigned long long n;
814 if (getAsUnsignedInteger(Scalar, 0, n))
815 return "invalid number";
816 if (n > 0xFFFF)
817 return "out of range number";
818 Val = n;
819 return StringRef();
820 }
821
output(const uint32_t & Val,void *,raw_ostream & Out)822 void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
823 raw_ostream &Out) {
824 Out << Val;
825 }
826
input(StringRef Scalar,void *,uint32_t & Val)827 StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
828 uint32_t &Val) {
829 unsigned long long n;
830 if (getAsUnsignedInteger(Scalar, 0, n))
831 return "invalid number";
832 if (n > 0xFFFFFFFFUL)
833 return "out of range number";
834 Val = n;
835 return StringRef();
836 }
837
output(const uint64_t & Val,void *,raw_ostream & Out)838 void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
839 raw_ostream &Out) {
840 Out << Val;
841 }
842
input(StringRef Scalar,void *,uint64_t & Val)843 StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
844 uint64_t &Val) {
845 unsigned long long N;
846 if (getAsUnsignedInteger(Scalar, 0, N))
847 return "invalid number";
848 Val = N;
849 return StringRef();
850 }
851
output(const int8_t & Val,void *,raw_ostream & Out)852 void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
853 // use temp in32_t because ostream thinks int8_t is a character
854 int32_t Num = Val;
855 Out << Num;
856 }
857
input(StringRef Scalar,void *,int8_t & Val)858 StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
859 long long N;
860 if (getAsSignedInteger(Scalar, 0, N))
861 return "invalid number";
862 if ((N > 127) || (N < -128))
863 return "out of range number";
864 Val = N;
865 return StringRef();
866 }
867
output(const int16_t & Val,void *,raw_ostream & Out)868 void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
869 raw_ostream &Out) {
870 Out << Val;
871 }
872
input(StringRef Scalar,void *,int16_t & Val)873 StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
874 long long N;
875 if (getAsSignedInteger(Scalar, 0, N))
876 return "invalid number";
877 if ((N > INT16_MAX) || (N < INT16_MIN))
878 return "out of range number";
879 Val = N;
880 return StringRef();
881 }
882
output(const int32_t & Val,void *,raw_ostream & Out)883 void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
884 raw_ostream &Out) {
885 Out << Val;
886 }
887
input(StringRef Scalar,void *,int32_t & Val)888 StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
889 long long N;
890 if (getAsSignedInteger(Scalar, 0, N))
891 return "invalid number";
892 if ((N > INT32_MAX) || (N < INT32_MIN))
893 return "out of range number";
894 Val = N;
895 return StringRef();
896 }
897
output(const int64_t & Val,void *,raw_ostream & Out)898 void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
899 raw_ostream &Out) {
900 Out << Val;
901 }
902
input(StringRef Scalar,void *,int64_t & Val)903 StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
904 long long N;
905 if (getAsSignedInteger(Scalar, 0, N))
906 return "invalid number";
907 Val = N;
908 return StringRef();
909 }
910
output(const double & Val,void *,raw_ostream & Out)911 void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
912 Out << format("%g", Val);
913 }
914
input(StringRef Scalar,void *,double & Val)915 StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
916 SmallString<32> buff(Scalar.begin(), Scalar.end());
917 char *end;
918 Val = strtod(buff.c_str(), &end);
919 if (*end != '\0')
920 return "invalid floating point number";
921 return StringRef();
922 }
923
output(const float & Val,void *,raw_ostream & Out)924 void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
925 Out << format("%g", Val);
926 }
927
input(StringRef Scalar,void *,float & Val)928 StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
929 SmallString<32> buff(Scalar.begin(), Scalar.end());
930 char *end;
931 Val = strtod(buff.c_str(), &end);
932 if (*end != '\0')
933 return "invalid floating point number";
934 return StringRef();
935 }
936
output(const Hex8 & Val,void *,raw_ostream & Out)937 void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
938 uint8_t Num = Val;
939 Out << format("0x%02X", Num);
940 }
941
input(StringRef Scalar,void *,Hex8 & Val)942 StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
943 unsigned long long n;
944 if (getAsUnsignedInteger(Scalar, 0, n))
945 return "invalid hex8 number";
946 if (n > 0xFF)
947 return "out of range hex8 number";
948 Val = n;
949 return StringRef();
950 }
951
output(const Hex16 & Val,void *,raw_ostream & Out)952 void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
953 uint16_t Num = Val;
954 Out << format("0x%04X", Num);
955 }
956
input(StringRef Scalar,void *,Hex16 & Val)957 StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
958 unsigned long long n;
959 if (getAsUnsignedInteger(Scalar, 0, n))
960 return "invalid hex16 number";
961 if (n > 0xFFFF)
962 return "out of range hex16 number";
963 Val = n;
964 return StringRef();
965 }
966
output(const Hex32 & Val,void *,raw_ostream & Out)967 void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
968 uint32_t Num = Val;
969 Out << format("0x%08X", Num);
970 }
971
input(StringRef Scalar,void *,Hex32 & Val)972 StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
973 unsigned long long n;
974 if (getAsUnsignedInteger(Scalar, 0, n))
975 return "invalid hex32 number";
976 if (n > 0xFFFFFFFFUL)
977 return "out of range hex32 number";
978 Val = n;
979 return StringRef();
980 }
981
output(const Hex64 & Val,void *,raw_ostream & Out)982 void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
983 uint64_t Num = Val;
984 Out << format("0x%016llX", Num);
985 }
986
input(StringRef Scalar,void *,Hex64 & Val)987 StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
988 unsigned long long Num;
989 if (getAsUnsignedInteger(Scalar, 0, Num))
990 return "invalid hex64 number";
991 Val = Num;
992 return StringRef();
993 }
994