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 this->output(" ");
427 this->output(Tag);
428 }
429 return Use;
430 }
431
endMapping()432 void Output::endMapping() {
433 StateStack.pop_back();
434 }
435
preflightKey(const char * Key,bool Required,bool SameAsDefault,bool & UseDefault,void * &)436 bool Output::preflightKey(const char *Key, bool Required, bool SameAsDefault,
437 bool &UseDefault, void *&) {
438 UseDefault = false;
439 if (Required || !SameAsDefault) {
440 auto State = StateStack.back();
441 if (State == inFlowMapFirstKey || State == inFlowMapOtherKey) {
442 flowKey(Key);
443 } else {
444 this->newLineCheck();
445 this->paddedKey(Key);
446 }
447 return true;
448 }
449 return false;
450 }
451
postflightKey(void *)452 void Output::postflightKey(void *) {
453 if (StateStack.back() == inMapFirstKey) {
454 StateStack.pop_back();
455 StateStack.push_back(inMapOtherKey);
456 } else if (StateStack.back() == inFlowMapFirstKey) {
457 StateStack.pop_back();
458 StateStack.push_back(inFlowMapOtherKey);
459 }
460 }
461
beginFlowMapping()462 void Output::beginFlowMapping() {
463 StateStack.push_back(inFlowMapFirstKey);
464 this->newLineCheck();
465 ColumnAtMapFlowStart = Column;
466 output("{ ");
467 }
468
endFlowMapping()469 void Output::endFlowMapping() {
470 StateStack.pop_back();
471 this->outputUpToEndOfLine(" }");
472 }
473
beginDocuments()474 void Output::beginDocuments() {
475 this->outputUpToEndOfLine("---");
476 }
477
preflightDocument(unsigned index)478 bool Output::preflightDocument(unsigned index) {
479 if (index > 0)
480 this->outputUpToEndOfLine("\n---");
481 return true;
482 }
483
postflightDocument()484 void Output::postflightDocument() {
485 }
486
endDocuments()487 void Output::endDocuments() {
488 output("\n...\n");
489 }
490
beginSequence()491 unsigned Output::beginSequence() {
492 StateStack.push_back(inSeq);
493 NeedsNewLine = true;
494 return 0;
495 }
496
endSequence()497 void Output::endSequence() {
498 StateStack.pop_back();
499 }
500
preflightElement(unsigned,void * &)501 bool Output::preflightElement(unsigned, void *&) {
502 return true;
503 }
504
postflightElement(void *)505 void Output::postflightElement(void *) {
506 }
507
beginFlowSequence()508 unsigned Output::beginFlowSequence() {
509 StateStack.push_back(inFlowSeq);
510 this->newLineCheck();
511 ColumnAtFlowStart = Column;
512 output("[ ");
513 NeedFlowSequenceComma = false;
514 return 0;
515 }
516
endFlowSequence()517 void Output::endFlowSequence() {
518 StateStack.pop_back();
519 this->outputUpToEndOfLine(" ]");
520 }
521
preflightFlowElement(unsigned,void * &)522 bool Output::preflightFlowElement(unsigned, void *&) {
523 if (NeedFlowSequenceComma)
524 output(", ");
525 if (WrapColumn && Column > WrapColumn) {
526 output("\n");
527 for (int i = 0; i < ColumnAtFlowStart; ++i)
528 output(" ");
529 Column = ColumnAtFlowStart;
530 output(" ");
531 }
532 return true;
533 }
534
postflightFlowElement(void *)535 void Output::postflightFlowElement(void *) {
536 NeedFlowSequenceComma = true;
537 }
538
beginEnumScalar()539 void Output::beginEnumScalar() {
540 EnumerationMatchFound = false;
541 }
542
matchEnumScalar(const char * Str,bool Match)543 bool Output::matchEnumScalar(const char *Str, bool Match) {
544 if (Match && !EnumerationMatchFound) {
545 this->newLineCheck();
546 this->outputUpToEndOfLine(Str);
547 EnumerationMatchFound = true;
548 }
549 return false;
550 }
551
matchEnumFallback()552 bool Output::matchEnumFallback() {
553 if (EnumerationMatchFound)
554 return false;
555 EnumerationMatchFound = true;
556 return true;
557 }
558
endEnumScalar()559 void Output::endEnumScalar() {
560 if (!EnumerationMatchFound)
561 llvm_unreachable("bad runtime enum value");
562 }
563
beginBitSetScalar(bool & DoClear)564 bool Output::beginBitSetScalar(bool &DoClear) {
565 this->newLineCheck();
566 output("[ ");
567 NeedBitValueComma = false;
568 DoClear = false;
569 return true;
570 }
571
bitSetMatch(const char * Str,bool Matches)572 bool Output::bitSetMatch(const char *Str, bool Matches) {
573 if (Matches) {
574 if (NeedBitValueComma)
575 output(", ");
576 this->output(Str);
577 NeedBitValueComma = true;
578 }
579 return false;
580 }
581
endBitSetScalar()582 void Output::endBitSetScalar() {
583 this->outputUpToEndOfLine(" ]");
584 }
585
scalarString(StringRef & S,bool MustQuote)586 void Output::scalarString(StringRef &S, bool MustQuote) {
587 this->newLineCheck();
588 if (S.empty()) {
589 // Print '' for the empty string because leaving the field empty is not
590 // allowed.
591 this->outputUpToEndOfLine("''");
592 return;
593 }
594 if (!MustQuote) {
595 // Only quote if we must.
596 this->outputUpToEndOfLine(S);
597 return;
598 }
599 unsigned i = 0;
600 unsigned j = 0;
601 unsigned End = S.size();
602 output("'"); // Starting single quote.
603 const char *Base = S.data();
604 while (j < End) {
605 // Escape a single quote by doubling it.
606 if (S[j] == '\'') {
607 output(StringRef(&Base[i], j - i + 1));
608 output("'");
609 i = j + 1;
610 }
611 ++j;
612 }
613 output(StringRef(&Base[i], j - i));
614 this->outputUpToEndOfLine("'"); // Ending single quote.
615 }
616
blockScalarString(StringRef & S)617 void Output::blockScalarString(StringRef &S) {
618 if (!StateStack.empty())
619 newLineCheck();
620 output(" |");
621 outputNewLine();
622
623 unsigned Indent = StateStack.empty() ? 1 : StateStack.size();
624
625 auto Buffer = MemoryBuffer::getMemBuffer(S, "", false);
626 for (line_iterator Lines(*Buffer, false); !Lines.is_at_end(); ++Lines) {
627 for (unsigned I = 0; I < Indent; ++I) {
628 output(" ");
629 }
630 output(*Lines);
631 outputNewLine();
632 }
633 }
634
setError(const Twine & message)635 void Output::setError(const Twine &message) {
636 }
637
canElideEmptySequence()638 bool Output::canElideEmptySequence() {
639 // Normally, with an optional key/value where the value is an empty sequence,
640 // the whole key/value can be not written. But, that produces wrong yaml
641 // if the key/value is the only thing in the map and the map is used in
642 // a sequence. This detects if the this sequence is the first key/value
643 // in map that itself is embedded in a sequnce.
644 if (StateStack.size() < 2)
645 return true;
646 if (StateStack.back() != inMapFirstKey)
647 return true;
648 return (StateStack[StateStack.size()-2] != inSeq);
649 }
650
output(StringRef s)651 void Output::output(StringRef s) {
652 Column += s.size();
653 Out << s;
654 }
655
outputUpToEndOfLine(StringRef s)656 void Output::outputUpToEndOfLine(StringRef s) {
657 this->output(s);
658 if (StateStack.empty() || (StateStack.back() != inFlowSeq &&
659 StateStack.back() != inFlowMapFirstKey &&
660 StateStack.back() != inFlowMapOtherKey))
661 NeedsNewLine = true;
662 }
663
outputNewLine()664 void Output::outputNewLine() {
665 Out << "\n";
666 Column = 0;
667 }
668
669 // if seq at top, indent as if map, then add "- "
670 // if seq in middle, use "- " if firstKey, else use " "
671 //
672
newLineCheck()673 void Output::newLineCheck() {
674 if (!NeedsNewLine)
675 return;
676 NeedsNewLine = false;
677
678 this->outputNewLine();
679
680 assert(StateStack.size() > 0);
681 unsigned Indent = StateStack.size() - 1;
682 bool OutputDash = false;
683
684 if (StateStack.back() == inSeq) {
685 OutputDash = true;
686 } else if ((StateStack.size() > 1) && ((StateStack.back() == inMapFirstKey) ||
687 (StateStack.back() == inFlowSeq) ||
688 (StateStack.back() == inFlowMapFirstKey)) &&
689 (StateStack[StateStack.size() - 2] == inSeq)) {
690 --Indent;
691 OutputDash = true;
692 }
693
694 for (unsigned i = 0; i < Indent; ++i) {
695 output(" ");
696 }
697 if (OutputDash) {
698 output("- ");
699 }
700
701 }
702
paddedKey(StringRef key)703 void Output::paddedKey(StringRef key) {
704 output(key);
705 output(":");
706 const char *spaces = " ";
707 if (key.size() < strlen(spaces))
708 output(&spaces[key.size()]);
709 else
710 output(" ");
711 }
712
flowKey(StringRef Key)713 void Output::flowKey(StringRef Key) {
714 if (StateStack.back() == inFlowMapOtherKey)
715 output(", ");
716 if (WrapColumn && Column > WrapColumn) {
717 output("\n");
718 for (int I = 0; I < ColumnAtMapFlowStart; ++I)
719 output(" ");
720 Column = ColumnAtMapFlowStart;
721 output(" ");
722 }
723 output(Key);
724 output(": ");
725 }
726
727 //===----------------------------------------------------------------------===//
728 // traits for built-in types
729 //===----------------------------------------------------------------------===//
730
output(const bool & Val,void *,raw_ostream & Out)731 void ScalarTraits<bool>::output(const bool &Val, void *, raw_ostream &Out) {
732 Out << (Val ? "true" : "false");
733 }
734
input(StringRef Scalar,void *,bool & Val)735 StringRef ScalarTraits<bool>::input(StringRef Scalar, void *, bool &Val) {
736 if (Scalar.equals("true")) {
737 Val = true;
738 return StringRef();
739 } else if (Scalar.equals("false")) {
740 Val = false;
741 return StringRef();
742 }
743 return "invalid boolean";
744 }
745
output(const StringRef & Val,void *,raw_ostream & Out)746 void ScalarTraits<StringRef>::output(const StringRef &Val, void *,
747 raw_ostream &Out) {
748 Out << Val;
749 }
750
input(StringRef Scalar,void *,StringRef & Val)751 StringRef ScalarTraits<StringRef>::input(StringRef Scalar, void *,
752 StringRef &Val) {
753 Val = Scalar;
754 return StringRef();
755 }
756
output(const std::string & Val,void *,raw_ostream & Out)757 void ScalarTraits<std::string>::output(const std::string &Val, void *,
758 raw_ostream &Out) {
759 Out << Val;
760 }
761
input(StringRef Scalar,void *,std::string & Val)762 StringRef ScalarTraits<std::string>::input(StringRef Scalar, void *,
763 std::string &Val) {
764 Val = Scalar.str();
765 return StringRef();
766 }
767
output(const uint8_t & Val,void *,raw_ostream & Out)768 void ScalarTraits<uint8_t>::output(const uint8_t &Val, void *,
769 raw_ostream &Out) {
770 // use temp uin32_t because ostream thinks uint8_t is a character
771 uint32_t Num = Val;
772 Out << Num;
773 }
774
input(StringRef Scalar,void *,uint8_t & Val)775 StringRef ScalarTraits<uint8_t>::input(StringRef Scalar, void *, uint8_t &Val) {
776 unsigned long long n;
777 if (getAsUnsignedInteger(Scalar, 0, n))
778 return "invalid number";
779 if (n > 0xFF)
780 return "out of range number";
781 Val = n;
782 return StringRef();
783 }
784
output(const uint16_t & Val,void *,raw_ostream & Out)785 void ScalarTraits<uint16_t>::output(const uint16_t &Val, void *,
786 raw_ostream &Out) {
787 Out << Val;
788 }
789
input(StringRef Scalar,void *,uint16_t & Val)790 StringRef ScalarTraits<uint16_t>::input(StringRef Scalar, void *,
791 uint16_t &Val) {
792 unsigned long long n;
793 if (getAsUnsignedInteger(Scalar, 0, n))
794 return "invalid number";
795 if (n > 0xFFFF)
796 return "out of range number";
797 Val = n;
798 return StringRef();
799 }
800
output(const uint32_t & Val,void *,raw_ostream & Out)801 void ScalarTraits<uint32_t>::output(const uint32_t &Val, void *,
802 raw_ostream &Out) {
803 Out << Val;
804 }
805
input(StringRef Scalar,void *,uint32_t & Val)806 StringRef ScalarTraits<uint32_t>::input(StringRef Scalar, void *,
807 uint32_t &Val) {
808 unsigned long long n;
809 if (getAsUnsignedInteger(Scalar, 0, n))
810 return "invalid number";
811 if (n > 0xFFFFFFFFUL)
812 return "out of range number";
813 Val = n;
814 return StringRef();
815 }
816
output(const uint64_t & Val,void *,raw_ostream & Out)817 void ScalarTraits<uint64_t>::output(const uint64_t &Val, void *,
818 raw_ostream &Out) {
819 Out << Val;
820 }
821
input(StringRef Scalar,void *,uint64_t & Val)822 StringRef ScalarTraits<uint64_t>::input(StringRef Scalar, void *,
823 uint64_t &Val) {
824 unsigned long long N;
825 if (getAsUnsignedInteger(Scalar, 0, N))
826 return "invalid number";
827 Val = N;
828 return StringRef();
829 }
830
output(const int8_t & Val,void *,raw_ostream & Out)831 void ScalarTraits<int8_t>::output(const int8_t &Val, void *, raw_ostream &Out) {
832 // use temp in32_t because ostream thinks int8_t is a character
833 int32_t Num = Val;
834 Out << Num;
835 }
836
input(StringRef Scalar,void *,int8_t & Val)837 StringRef ScalarTraits<int8_t>::input(StringRef Scalar, void *, int8_t &Val) {
838 long long N;
839 if (getAsSignedInteger(Scalar, 0, N))
840 return "invalid number";
841 if ((N > 127) || (N < -128))
842 return "out of range number";
843 Val = N;
844 return StringRef();
845 }
846
output(const int16_t & Val,void *,raw_ostream & Out)847 void ScalarTraits<int16_t>::output(const int16_t &Val, void *,
848 raw_ostream &Out) {
849 Out << Val;
850 }
851
input(StringRef Scalar,void *,int16_t & Val)852 StringRef ScalarTraits<int16_t>::input(StringRef Scalar, void *, int16_t &Val) {
853 long long N;
854 if (getAsSignedInteger(Scalar, 0, N))
855 return "invalid number";
856 if ((N > INT16_MAX) || (N < INT16_MIN))
857 return "out of range number";
858 Val = N;
859 return StringRef();
860 }
861
output(const int32_t & Val,void *,raw_ostream & Out)862 void ScalarTraits<int32_t>::output(const int32_t &Val, void *,
863 raw_ostream &Out) {
864 Out << Val;
865 }
866
input(StringRef Scalar,void *,int32_t & Val)867 StringRef ScalarTraits<int32_t>::input(StringRef Scalar, void *, int32_t &Val) {
868 long long N;
869 if (getAsSignedInteger(Scalar, 0, N))
870 return "invalid number";
871 if ((N > INT32_MAX) || (N < INT32_MIN))
872 return "out of range number";
873 Val = N;
874 return StringRef();
875 }
876
output(const int64_t & Val,void *,raw_ostream & Out)877 void ScalarTraits<int64_t>::output(const int64_t &Val, void *,
878 raw_ostream &Out) {
879 Out << Val;
880 }
881
input(StringRef Scalar,void *,int64_t & Val)882 StringRef ScalarTraits<int64_t>::input(StringRef Scalar, void *, int64_t &Val) {
883 long long N;
884 if (getAsSignedInteger(Scalar, 0, N))
885 return "invalid number";
886 Val = N;
887 return StringRef();
888 }
889
output(const double & Val,void *,raw_ostream & Out)890 void ScalarTraits<double>::output(const double &Val, void *, raw_ostream &Out) {
891 Out << format("%g", Val);
892 }
893
input(StringRef Scalar,void *,double & Val)894 StringRef ScalarTraits<double>::input(StringRef Scalar, void *, double &Val) {
895 SmallString<32> buff(Scalar.begin(), Scalar.end());
896 char *end;
897 Val = strtod(buff.c_str(), &end);
898 if (*end != '\0')
899 return "invalid floating point number";
900 return StringRef();
901 }
902
output(const float & Val,void *,raw_ostream & Out)903 void ScalarTraits<float>::output(const float &Val, void *, raw_ostream &Out) {
904 Out << format("%g", Val);
905 }
906
input(StringRef Scalar,void *,float & Val)907 StringRef ScalarTraits<float>::input(StringRef Scalar, void *, float &Val) {
908 SmallString<32> buff(Scalar.begin(), Scalar.end());
909 char *end;
910 Val = strtod(buff.c_str(), &end);
911 if (*end != '\0')
912 return "invalid floating point number";
913 return StringRef();
914 }
915
output(const Hex8 & Val,void *,raw_ostream & Out)916 void ScalarTraits<Hex8>::output(const Hex8 &Val, void *, raw_ostream &Out) {
917 uint8_t Num = Val;
918 Out << format("0x%02X", Num);
919 }
920
input(StringRef Scalar,void *,Hex8 & Val)921 StringRef ScalarTraits<Hex8>::input(StringRef Scalar, void *, Hex8 &Val) {
922 unsigned long long n;
923 if (getAsUnsignedInteger(Scalar, 0, n))
924 return "invalid hex8 number";
925 if (n > 0xFF)
926 return "out of range hex8 number";
927 Val = n;
928 return StringRef();
929 }
930
output(const Hex16 & Val,void *,raw_ostream & Out)931 void ScalarTraits<Hex16>::output(const Hex16 &Val, void *, raw_ostream &Out) {
932 uint16_t Num = Val;
933 Out << format("0x%04X", Num);
934 }
935
input(StringRef Scalar,void *,Hex16 & Val)936 StringRef ScalarTraits<Hex16>::input(StringRef Scalar, void *, Hex16 &Val) {
937 unsigned long long n;
938 if (getAsUnsignedInteger(Scalar, 0, n))
939 return "invalid hex16 number";
940 if (n > 0xFFFF)
941 return "out of range hex16 number";
942 Val = n;
943 return StringRef();
944 }
945
output(const Hex32 & Val,void *,raw_ostream & Out)946 void ScalarTraits<Hex32>::output(const Hex32 &Val, void *, raw_ostream &Out) {
947 uint32_t Num = Val;
948 Out << format("0x%08X", Num);
949 }
950
input(StringRef Scalar,void *,Hex32 & Val)951 StringRef ScalarTraits<Hex32>::input(StringRef Scalar, void *, Hex32 &Val) {
952 unsigned long long n;
953 if (getAsUnsignedInteger(Scalar, 0, n))
954 return "invalid hex32 number";
955 if (n > 0xFFFFFFFFUL)
956 return "out of range hex32 number";
957 Val = n;
958 return StringRef();
959 }
960
output(const Hex64 & Val,void *,raw_ostream & Out)961 void ScalarTraits<Hex64>::output(const Hex64 &Val, void *, raw_ostream &Out) {
962 uint64_t Num = Val;
963 Out << format("0x%016llX", Num);
964 }
965
input(StringRef Scalar,void *,Hex64 & Val)966 StringRef ScalarTraits<Hex64>::input(StringRef Scalar, void *, Hex64 &Val) {
967 unsigned long long Num;
968 if (getAsUnsignedInteger(Scalar, 0, Num))
969 return "invalid hex64 number";
970 Val = Num;
971 return StringRef();
972 }
973