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