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