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