1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "ast.h"
10 
11 #include <iomanip>
12 #include <set>
13 #include <sstream>
14 
15 #include "logger.h"
16 
17 using namespace OHOS::Hardware;
18 
19 static constexpr int FOUR_MULTIPLE = 4;
20 
AstObject(const std::string & name,uint32_t type,uint64_t integerValue,const std::string & strValue,uint32_t lineno,const std::shared_ptr<std::string> & src)21 AstObject::AstObject(const std::string &name, uint32_t type, uint64_t integerValue, const std::string &strValue,
22     uint32_t lineno, const std::shared_ptr<std::string> &src)
23     : type_(type),
24       name_(name),
25       parent_(nullptr),
26       next_(nullptr),
27       child_(nullptr),
28       lineno_(lineno),
29       src_(src),
30       opCode_(0),
31       size_(0),
32       subSize_(0),
33       hash_(0),
34       integerValue_(integerValue),
35       stringValue_(strValue)
36 {
37 }
38 
AstObject(const std::string & name,uint32_t type,uint64_t integerValue)39 AstObject::AstObject(const std::string &name, uint32_t type, uint64_t integerValue)
40     : AstObject(name, type, integerValue, "", 0, nullptr)
41 {
42 }
43 
AstObject(const std::string & name,uint32_t type,const std::string & strValue)44 AstObject::AstObject(const std::string &name, uint32_t type, const std::string &strValue)
45     : AstObject(name, type, 0, strValue, 0, nullptr)
46 {
47 }
48 
AstObject(const std::string & name,uint32_t type,uint64_t integerValue,const Token & bindToken)49 AstObject::AstObject(const std::string &name, uint32_t type, uint64_t integerValue, const Token &bindToken)
50     : AstObject(name, type, integerValue, "", bindToken.lineNo, bindToken.src)
51 {
52     switch (type) {
53         case PARSEROP_UINT8:  /* fall-through */
54         case PARSEROP_UINT16: /* fall-through */
55         case PARSEROP_UINT32: /* fall-through */
56         case PARSEROP_UINT64:
57             this->type_ = FitIntegerValueType(integerValue);
58             break;
59         default:
60             break;
61     }
62 }
63 
AstObject(const std::string & name,uint32_t type,const std::string & strValue,const Token & bindToken)64 AstObject::AstObject(const std::string &name, uint32_t type, const std::string &strValue, const Token &bindToken)
65     : AstObject(name, type, 0, strValue, bindToken.lineNo, bindToken.src)
66 {
67 }
68 
AstObject(const AstObject & obj)69 AstObject::AstObject(const AstObject &obj)
70     : AstObject(obj.name_, obj.type_, obj.integerValue_, obj.stringValue_, 0, obj.src_)
71 {
72 }
73 
~AstObject()74 AstObject::~AstObject()
75 {
76     parent_ = nullptr;
77     next_ = nullptr;
78     child_ = nullptr;
79 }
80 
operator =(const AstObject & obj)81 AstObject &AstObject::operator=(const AstObject &obj)
82 {
83     if (this != &obj) {
84         type_ = obj.type_;
85         name_ = obj.name_;
86         parent_ = obj.parent_;
87         next_ = obj.next_;
88         child_ = obj.child_;
89         lineno_ = obj.lineno_;
90         src_ = obj.src_;
91         opCode_ = obj.opCode_;
92         size_ = obj.size_;
93         subSize_ = obj.subSize_;
94         hash_ = obj.hash_;
95         integerValue_ = obj.integerValue_;
96         stringValue_ = obj.stringValue_;
97     }
98 
99     return *this;
100 }
101 
FitIntegerValueType(uint64_t value)102 uint32_t AstObject::FitIntegerValueType(uint64_t value)
103 {
104     if (value <= UINT8_MAX) {
105         return PARSEROP_UINT8;
106     } else if (value <= UINT16_MAX) {
107         return PARSEROP_UINT16;
108     } else if (value <= UINT32_MAX) {
109         return PARSEROP_UINT32;
110     } else {
111         return PARSEROP_UINT64;
112     }
113 }
114 
AddChild(const std::shared_ptr<AstObject> & childObj)115 bool AstObject::AddChild(const std::shared_ptr<AstObject> &childObj)
116 {
117     if (childObj == nullptr) {
118         return false;
119     }
120     if (child_ == nullptr) {
121         child_ = childObj;
122         std::shared_ptr<AstObject> childNext = childObj;
123         while (childNext != nullptr) {
124             childNext->parent_ = this;
125             childNext = childNext->next_;
126         }
127     } else {
128         return child_->AddPeer(childObj);
129     }
130 
131     return true;
132 }
133 
AddPeer(std::shared_ptr<AstObject> peerObject)134 bool AstObject::AddPeer(std::shared_ptr<AstObject> peerObject)
135 {
136     if (peerObject == nullptr) {
137         return false;
138     }
139 
140     if (this == peerObject.get()) {
141         Logger().Error() << "add self as peer";
142         return false;
143     }
144 
145     if (next_ == nullptr) {
146         next_ = peerObject;
147     } else {
148         std::shared_ptr<AstObject> lastNode = next_;
149         while (lastNode->next_ != nullptr) {
150             lastNode = lastNode->next_;
151         }
152         lastNode->next_ = peerObject;
153     }
154 
155     std::shared_ptr<AstObject> peer = peerObject;
156     while (peer) {
157         peer->parent_ = parent_;
158         peer = peer->next_;
159     }
160 
161     return true;
162 }
163 
operator <<(std::ostream & stream,const AstObject & t)164 std::ostream &OHOS::Hardware::operator<<(std::ostream &stream, const AstObject &t)
165 {
166     if (t.type_ == PARSEROP_CONFNODE) {
167         auto node = static_cast<const ConfigNode *>(&t);
168         stream << *node;
169         return stream;
170     } else if (t.type_ == PARSEROP_CONFTERM) {
171         auto term = static_cast<const ConfigTerm *>(&t);
172         stream << *term;
173         return stream;
174     }
175 
176     if (t.name_.empty()) {
177         stream << "|_";
178     } else {
179         stream << t.name_;
180     }
181     switch (t.type_) {
182         case PARSEROP_UINT8:
183             stream << "uint8 0x" << std::hex << t.integerValue_;
184             break;
185         case PARSEROP_UINT16:
186             stream << "uint16 0x" << std::hex << t.integerValue_;
187             break;
188         case PARSEROP_UINT32:
189             stream << "uint32 0x" << std::hex << t.integerValue_;
190             break;
191         case PARSEROP_UINT64:
192             stream << "uint64 0x" << std::hex << t.integerValue_;
193             break;
194         case PARSEROP_STRING:
195             stream << "string \"" << t.stringValue_ << "\"";
196             break;
197         case PARSEROP_ARRAY:
198             stream << "array";
199             break;
200         case PARSEROP_NODEREF:
201             stream << "noderef " << t.stringValue_;
202             break;
203         case PARSEROP_DELETE:
204             stream << "delete";
205             break;
206         default:
207             break;
208     }
209     return stream;
210 }
211 
Merge(std::shared_ptr<AstObject> & srcObj)212 bool AstObject::Merge(std::shared_ptr<AstObject> &srcObj)
213 {
214     if (srcObj->name_ != name_) {
215         Logger().Error() << this->SourceInfo() << "merge different node to" << srcObj->SourceInfo();
216         return false;
217     }
218 
219     if (srcObj->type_ != type_) {
220         Logger().Error() << this->SourceInfo() << "conflict type with " << srcObj->SourceInfo();
221         return false;
222     }
223 
224     src_ = srcObj->src_;
225     lineno_ = srcObj->lineno_;
226     stringValue_ = srcObj->stringValue_;
227     integerValue_ = srcObj->integerValue_;
228 
229     return true;
230 }
231 
Copy(std::shared_ptr<AstObject> src,bool overwrite)232 bool AstObject::Copy(std::shared_ptr<AstObject> src, bool overwrite)
233 {
234     if (src == nullptr) {
235         return false;
236     }
237 
238     if (overwrite) {
239         src_ = src->src_;
240         lineno_ = src->lineno_;
241         integerValue_ = src->integerValue_;
242         stringValue_ = src->stringValue_;
243     }
244 
245     return true;
246 }
247 
Move(std::shared_ptr<AstObject> src)248 bool AstObject::Move(std::shared_ptr<AstObject> src)
249 {
250     if (!Copy(src, true)) {
251         return false;
252     }
253     src->Separate();
254     return true;
255 }
256 
SourceInfo()257 std::string AstObject::SourceInfo()
258 {
259     if (src_ == nullptr) {
260         return "unknown";
261     }
262     std::stringstream o;
263     o << src_->c_str() << ":" << lineno_ << " ";
264     return o.str();
265 }
266 
Remove()267 void AstObject::Remove()
268 {
269     Separate();
270     child_ = nullptr;
271     next_ = nullptr;
272 }
273 
Lookup(const std::string & name,uint32_t type) const274 std::shared_ptr<AstObject> AstObject::Lookup(const std::string &name, uint32_t type) const
275 {
276     auto peer = child_;
277     while (peer != nullptr) {
278         if (peer->name_ == name && (type == 0 || peer->type_ == type)) {
279             return peer;
280         }
281 
282         peer = peer->next_;
283     }
284 
285     return nullptr;
286 }
287 
IsNumber() const288 bool AstObject::IsNumber() const
289 {
290     return type_ >= PARSEROP_UINT8 && type_ <= PARSEROP_UINT64;
291 }
292 
IsNode() const293 bool AstObject::IsNode() const
294 {
295     return type_ == PARSEROP_CONFNODE;
296 }
297 
IsTerm() const298 bool AstObject::IsTerm() const
299 {
300     return type_ == PARSEROP_CONFTERM;
301 }
302 
IsArray() const303 bool AstObject::IsArray() const
304 {
305     return type_ == PARSEROP_ARRAY;
306 }
307 
Separate()308 void AstObject::Separate()
309 {
310     if (parent_ == nullptr) {
311         return;
312     }
313     if (parent_->child_.get() == this) {
314         parent_->child_ = next_; // decref this
315         next_ = nullptr;
316         return;
317     }
318 
319     auto pre = parent_->child_;
320     while (pre != nullptr) {
321         if (pre->next_.get() == this) {
322             pre->next_ = pre->next_->next_; // decref this
323             break;
324         }
325 
326         pre = pre->next_;
327     }
328     next_ = nullptr;
329 }
330 
SetParent(AstObject * parent)331 void AstObject::SetParent(AstObject *parent)
332 {
333     parent_ = parent;
334 }
335 
SetSize(uint32_t size)336 void AstObject::SetSize(uint32_t size)
337 {
338     size_ = size;
339 }
340 
SetSubSize(uint32_t size)341 void AstObject::SetSubSize(uint32_t size)
342 {
343     subSize_ = size;
344 }
345 
GetSubSize() const346 uint32_t AstObject::GetSubSize() const
347 {
348     return subSize_;
349 }
350 
SetHash(uint32_t hash)351 void AstObject::SetHash(uint32_t hash)
352 {
353     hash_ = hash;
354 }
355 
GetSize() const356 uint32_t AstObject::GetSize() const
357 {
358     return size_;
359 }
360 
GetHash() const361 uint32_t AstObject::GetHash() const
362 {
363     return hash_;
364 }
365 
Next()366 std::shared_ptr<AstObject> AstObject::Next()
367 {
368     return next_;
369 }
370 
Child()371 std::shared_ptr<AstObject> AstObject::Child()
372 {
373     return child_;
374 }
375 
Name()376 const std::string &AstObject::Name()
377 {
378     return name_;
379 }
380 
StringValue() const381 const std::string &AstObject::StringValue() const
382 {
383     return stringValue_;
384 }
385 
IntegerValue() const386 uint64_t AstObject::IntegerValue() const
387 {
388     return integerValue_;
389 }
390 
Type()391 uint32_t AstObject::Type()
392 {
393     return type_;
394 }
395 
OpCode() const396 uint8_t AstObject::OpCode() const
397 {
398     return opCode_;
399 }
400 
SetOpCode(uint8_t opcode)401 void AstObject::SetOpCode(uint8_t opcode)
402 {
403     opCode_ = opcode;
404 }
405 
HasDuplicateChild()406 bool AstObject::HasDuplicateChild()
407 {
408     return false;
409 }
410 
IsElders(const std::shared_ptr<AstObject> & child) const411 bool AstObject::IsElders(const std::shared_ptr<AstObject> &child) const
412 {
413     auto p = child.get();
414     while (p != nullptr) {
415         if (p == this) {
416             return true;
417         }
418         p = p->parent_;
419     }
420     return false;
421 }
422 
Parent() const423 std::shared_ptr<AstObject> AstObject::Parent() const
424 {
425     return std::shared_ptr<AstObject>(parent_, [](auto p) { (void)p; });
426 }
427 
ConfigNode(const ConfigNode & node)428 ConfigNode::ConfigNode(const ConfigNode &node) : ConfigNode(node.name_, node.nodeType_, node.refNodePath_)
429 {
430     auto child = node.child_;
431     while (child != nullptr) {
432         AstObject::AddChild(AstObjectFactory::Build(child));
433         child = child->Next();
434     }
435 }
436 
ConfigNode(const std::string & name,uint32_t nodeType,const std::string & refName)437 ConfigNode::ConfigNode(const std::string &name, uint32_t nodeType, const std::string &refName)
438     : AstObject(name, PARSEROP_CONFNODE, ""),
439       refNodePath_(refName),
440       nodeType_(nodeType),
441       inheritIndex_(0),
442       inheritCount_(0),
443       templateSignNum_(0)
444 {
445 }
446 
ConfigNode(Token & name,uint32_t nodeType,const std::string & refName)447 ConfigNode::ConfigNode(Token &name, uint32_t nodeType, const std::string &refName)
448     : AstObject(name.strval, PARSEROP_CONFNODE, 0, name),
449       refNodePath_(refName),
450       nodeType_(nodeType),
451       inheritIndex_(0),
452       inheritCount_(0),
453       templateSignNum_(0)
454 {
455 }
456 
operator =(const ConfigNode & node)457 ConfigNode &ConfigNode::operator=(const ConfigNode &node)
458 {
459     if (this != &node) {
460         refNodePath_ = node.refNodePath_;
461         nodeType_ = node.nodeType_;
462         inheritIndex_ = node.inheritIndex_;
463         inheritCount_ = node.inheritCount_;
464         templateSignNum_ = node.templateSignNum_;
465         subClasses_ = node.subClasses_;
466     }
467 
468     return *this;
469 }
470 
NodeTypeToStr(uint32_t type)471 const std::string &ConfigNode::NodeTypeToStr(uint32_t type)
472 {
473     static std::map<uint32_t, std::string> type2StringMap = {
474         {NODE_NOREF,    ""             },
475         {NODE_COPY,     "NodeCopy"     },
476         {NODE_REF,      "NodeReference"},
477         {NODE_DELETE,   "NodeDelete"   },
478         {NODE_INHERIT,  "NodeInherit"  },
479         {NODE_TEMPLATE, "NodeTemplate" },
480     };
481     return type2StringMap[type];
482 }
483 
operator <<(std::ostream & stream,const ConfigNode & t)484 std::ostream &OHOS::Hardware::operator<<(std::ostream &stream, const ConfigNode &t)
485 {
486     stream << "[node] " << t.name_ << " " << ConfigNode::NodeTypeToStr(t.nodeType_) << " "
487            << t.refNodePath_;
488     return stream;
489 }
490 
CastFrom(const std::shared_ptr<AstObject> & astObject)491 ConfigNode *ConfigNode::CastFrom(const std::shared_ptr<AstObject> &astObject)
492 {
493     return dynamic_cast<ConfigNode *>(astObject.get());
494 }
495 
GetNodeType() const496 uint32_t ConfigNode::GetNodeType() const
497 {
498     return nodeType_;
499 }
500 
GetRefPath() const501 const std::string &ConfigNode::GetRefPath() const
502 {
503     return refNodePath_;
504 }
505 
Merge(std::shared_ptr<AstObject> & srcObj)506 bool ConfigNode::Merge(std::shared_ptr<AstObject> &srcObj)
507 {
508     if (srcObj == nullptr) {
509         return true;
510     }
511     if (!srcObj->IsNode() || srcObj->Name() != name_) {
512         Logger().Error() << SourceInfo() << "merge conflict type with " << srcObj->SourceInfo();
513         return false;
514     }
515 
516     auto srcNode = ConfigNode::CastFrom(srcObj);
517     if (srcNode->GetNodeType() == DELETE) {
518         srcObj->Separate();
519         this->Separate();
520         return true;
521     }
522 
523     nodeType_ = srcNode->nodeType_;
524     refNodePath_ = srcNode->refNodePath_;
525 
526     auto childSrc = srcObj->Child();
527     while (childSrc != nullptr) {
528         auto childSrcNext = childSrc->Next();
529         auto childDst = Lookup(childSrc->Name(), childSrc->Type());
530         if (childDst == nullptr) {
531             childSrc->Separate();
532             AddChild(childSrc);
533         } else {
534             if (!childDst->Merge(childSrc)) {
535                 return false;
536             }
537         }
538         childSrc = childSrcNext;
539     }
540     return true;
541 }
542 
SetNodeType(uint32_t nodeType)543 void ConfigNode::SetNodeType(uint32_t nodeType)
544 {
545     nodeType_ = nodeType;
546 }
547 
SetRefPath(const std::string & ref)548 void ConfigNode::SetRefPath(const std::string &ref)
549 {
550     refNodePath_ = ref;
551 }
552 
HasDuplicateChild()553 bool ConfigNode::HasDuplicateChild()
554 {
555     std::map<std::string, std::shared_ptr<AstObject>> symMap;
556     auto child = child_;
557     while (child != nullptr) {
558         auto sym = symMap.find(child->Name());
559         if (sym != symMap.end()) {
560             Logger().Error() << child->SourceInfo() << "redefined, first definition at " << sym->second->SourceInfo();
561             return true;
562         }
563         symMap[child->Name()] = child;
564         child = child->Next();
565     }
566 
567     return false;
568 }
569 
InheritExpand(const std::shared_ptr<AstObject> & refObj)570 bool ConfigNode::InheritExpand(const std::shared_ptr<AstObject> &refObj)
571 {
572     if (refObj == nullptr) {
573         Logger().Error() << SourceInfo() << "inherit invalid node: " << refNodePath_;
574         return false;
575     }
576 
577     if (!Copy(refObj, false)) {
578         return false;
579     }
580 
581     auto templateNode = ConfigNode::CastFrom(refObj);
582     if (!Compare(*templateNode)) {
583         return false;
584     }
585     inheritIndex_ = templateNode->inheritCount_++;
586     templateNode->subClasses_.push_back(this);
587     return true;
588 }
589 
RefExpand(const std::shared_ptr<AstObject> & refObj)590 bool ConfigNode::RefExpand(const std::shared_ptr<AstObject> &refObj)
591 {
592     if (nodeType_ == NODE_DELETE) {
593         this->Separate();
594         return true;
595     }
596 
597     if (refObj->IsElders(std::shared_ptr<AstObject>(this, [](auto p) { (void)p; }))) {
598         Logger().Error() << SourceInfo() << "circular reference " << refObj->SourceInfo();
599         return false;
600     }
601 
602     bool ret = true;
603     if (nodeType_ == NODE_REF) {
604         ret = NodeRefExpand(refObj);
605     } else if (nodeType_ == NODE_COPY) {
606         ret = NodeCopyExpand(refObj);
607     }
608 
609     return ret;
610 }
611 
Copy(std::shared_ptr<AstObject> src,bool overwrite)612 bool ConfigNode::Copy(std::shared_ptr<AstObject> src, bool overwrite)
613 {
614     if (!src->IsNode()) {
615         Logger().Error() << SourceInfo() << "node copy with different type " << src->SourceInfo();
616         return false;
617     }
618     auto child = src->Child();
619     while (child != nullptr) {
620         auto dst = Lookup(child->Name(), child->Type());
621         if (dst == nullptr) {
622             AddChild(AstObjectFactory::Build(child));
623         } else {
624             if (!dst->Copy(child, overwrite)) {
625                 return false;
626             }
627         }
628         child = child->Next();
629     }
630 
631     return true;
632 }
633 
Move(std::shared_ptr<AstObject> src)634 bool ConfigNode::Move(std::shared_ptr<AstObject> src)
635 {
636     return AstObject::Move(src);
637 }
638 
NodeRefExpand(const std::shared_ptr<AstObject> & ref)639 bool ConfigNode::NodeRefExpand(const std::shared_ptr<AstObject> &ref)
640 {
641     if (ref == nullptr) {
642         Logger().Error() << SourceInfo() << "reference node '" << refNodePath_ << "' not exist";
643         return false;
644     }
645     return ref->Move(std::shared_ptr<AstObject>(this, [](AstObject *p) {
646         (void)p;
647     }));
648 }
649 
NodeCopyExpand(const std::shared_ptr<AstObject> & ref)650 bool ConfigNode::NodeCopyExpand(const std::shared_ptr<AstObject> &ref)
651 {
652     if (ref == nullptr) {
653         return false;
654     }
655     this->nodeType_ = NODE_NOREF;
656     return Copy(ref, false);
657 }
658 
Compare(ConfigNode & other) const659 bool ConfigNode::Compare(ConfigNode &other) const
660 {
661     auto objChild = child_;
662     while (objChild != nullptr) {
663         auto baseObj = Lookup(objChild->Name(), objChild->Type());
664         if (baseObj == nullptr) {
665             Logger().Error() << objChild->SourceInfo() << "not in template node: " << other.SourceInfo();
666             return false;
667         }
668         if (objChild->IsNode()) {
669             return ConfigNode::CastFrom(objChild)->Compare(*ConfigNode::CastFrom(baseObj));
670         }
671 
672         objChild = objChild->Next();
673     }
674     return true;
675 }
676 
InheritIndex() const677 uint32_t ConfigNode::InheritIndex() const
678 {
679     return inheritIndex_;
680 }
681 
InheritCount() const682 uint32_t ConfigNode::InheritCount() const
683 {
684     return inheritCount_;
685 }
686 
TemplateSignNum() const687 uint32_t ConfigNode::TemplateSignNum() const
688 {
689     return templateSignNum_;
690 }
691 
SetTemplateSignNum(uint32_t sigNum)692 void ConfigNode::SetTemplateSignNum(uint32_t sigNum)
693 {
694     templateSignNum_ = sigNum;
695 }
696 
SubClasses() const697 const std::list<AstObject *> &ConfigNode::SubClasses() const
698 {
699     return subClasses_;
700 }
701 
IsBaseNode()702 bool ConfigNode::IsBaseNode()
703 {
704     if (GetNodeType() != NODE_NOREF && GetNodeType() != NODE_TEMPLATE) {
705         return false;
706     }
707     for (auto obj = Child(); obj != nullptr; obj = obj->Next()) {
708         if (!obj->IsNode()) {
709             continue;
710         }
711         if (!CastFrom(obj)->IsBaseNode()) {
712             return false;
713         }
714     }
715 
716     return true;
717 }
718 
ConfigTerm(const ConfigTerm & term)719 ConfigTerm::ConfigTerm(const ConfigTerm &term) : ConfigTerm(term.name_, nullptr)
720 {
721     AstObject::AddChild(AstObjectFactory::Build(term.child_));
722     src_ = term.src_;
723     lineno_ = term.lineno_;
724 }
725 
ConfigTerm(const std::string & name,const std::shared_ptr<AstObject> & value)726 ConfigTerm::ConfigTerm(const std::string &name, const std::shared_ptr<AstObject> &value)
727     : AstObject(name, PARSEROP_CONFTERM, 0), signNum_(0)
728 {
729     if (value != nullptr) {
730         child_ = value;
731         value->SetParent(this);
732     }
733 }
734 
ConfigTerm(Token & name,const std::shared_ptr<AstObject> & value)735 ConfigTerm::ConfigTerm(Token &name, const std::shared_ptr<AstObject> &value)
736     : AstObject(name.strval, PARSEROP_CONFTERM, 0, name), signNum_(0)
737 {
738     if (value != nullptr) {
739         child_ = value;
740         value->SetParent(this);
741     }
742 }
743 
operator =(const ConfigTerm & term)744 ConfigTerm &ConfigTerm::operator=(const ConfigTerm &term)
745 {
746     if (this != &term) {
747         refNode_ = term.refNode_;
748         signNum_ = term.signNum_;
749     }
750 
751     return *this;
752 }
753 
operator <<(std::ostream & stream,const ConfigTerm & t)754 std::ostream &OHOS::Hardware::operator<<(std::ostream &stream, const ConfigTerm &t)
755 {
756     stream << "[term] " << t.name_;
757     return stream;
758 }
759 
CastFrom(const std::shared_ptr<AstObject> & astObject)760 ConfigTerm *ConfigTerm::CastFrom(const std::shared_ptr<AstObject> &astObject)
761 {
762     return dynamic_cast<ConfigTerm *>(astObject.get());
763 }
764 
Merge(std::shared_ptr<AstObject> & srcObj)765 bool ConfigTerm::Merge(std::shared_ptr<AstObject> &srcObj)
766 {
767     if (!srcObj->IsTerm()) {
768         Logger().Error() << SourceInfo() << "merge conflict type with " << srcObj->SourceInfo();
769         return false;
770     }
771 
772     auto value = srcObj->Child();
773     srcObj->Child()->Separate();
774     child_ = nullptr;
775     AddChild(value);
776     return true;
777 }
778 
RefExpand(const std::shared_ptr<AstObject> refObj)779 bool ConfigTerm::RefExpand(const std::shared_ptr<AstObject> refObj)
780 {
781     if (child_->Type() == PARSEROP_DELETE) {
782         this->Separate();
783         return true;
784     }
785 
786     if (child_->Type() != PARSEROP_NODEREF) {
787         return true;
788     }
789 
790     if (refObj == nullptr || !refObj->IsNode() || ConfigNode::CastFrom(refObj)->GetNodeType() == NODE_REF ||
791         ConfigNode::CastFrom(refObj)->GetNodeType() == NODE_TEMPLATE ||
792         ConfigNode::CastFrom(refObj)->GetNodeType() == NODE_DELETE) {
793         Logger().Error() << SourceInfo() << "reference invalid node '" << child_->StringValue() << '\'';
794         return false;
795     }
796 
797     refNode_ = refObj;
798     return true;
799 }
800 
Copy(std::shared_ptr<AstObject> src,bool overwrite)801 bool ConfigTerm::Copy(std::shared_ptr<AstObject> src, bool overwrite)
802 {
803     if (!overwrite) {
804         return true;
805     }
806     if (child_->Type() != src->Child()->Type() && (!child_->IsNumber() || !src->Child()->IsNumber())) {
807         Logger().Error() << src->SourceInfo() << "overwrite different type with:" << child_->SourceInfo();
808         return false;
809     }
810     return child_->Copy(src->Child(), overwrite);
811 }
812 
Move(std::shared_ptr<AstObject> src)813 bool ConfigTerm::Move(std::shared_ptr<AstObject> src)
814 {
815     return child_->Move(src->Child());
816 }
817 
RefNode()818 std::weak_ptr<AstObject> ConfigTerm::RefNode()
819 {
820     return refNode_;
821 }
822 
SetSigNum(uint32_t sigNum)823 void ConfigTerm::SetSigNum(uint32_t sigNum)
824 {
825     signNum_ = sigNum;
826 }
827 
SigNum() const828 uint32_t ConfigTerm::SigNum() const
829 {
830     return signNum_;
831 }
832 
ConfigArray()833 ConfigArray::ConfigArray() : AstObject("", PARSEROP_ARRAY, 0), arrayType_(0), arraySize_(0) {}
834 
ConfigArray(const ConfigArray & array)835 ConfigArray::ConfigArray(const ConfigArray &array) : ConfigArray()
836 {
837     auto child = array.child_;
838     while (child != nullptr) {
839         AstObject::AddChild(AstObjectFactory::Build(child));
840         child = child->Next();
841     }
842     arraySize_ = array.arraySize_;
843     arrayType_ = array.arrayType_;
844 }
845 
ConfigArray(const Token & bindToken)846 ConfigArray::ConfigArray(const Token &bindToken)
847     : AstObject("", PARSEROP_ARRAY, 0, bindToken), arrayType_(0), arraySize_(0)
848 {
849 }
850 
operator =(const ConfigArray & array)851 ConfigArray &ConfigArray::operator=(const ConfigArray &array)
852 {
853     if (this != &array) {
854         arrayType_ = array.arrayType_;
855         arraySize_ = array.arraySize_;
856     }
857 
858     return *this;
859 }
860 
AddChild(const std::shared_ptr<AstObject> & childObj)861 bool ConfigArray::AddChild(const std::shared_ptr<AstObject> &childObj)
862 {
863     if (AstObject::AddChild(childObj)) {
864         arraySize_++;
865         arrayType_ = std::max(arrayType_, childObj->Type());
866         return true;
867     } else {
868         return false;
869     }
870 }
871 
Merge(std::shared_ptr<AstObject> & srcObj)872 bool ConfigArray::Merge(std::shared_ptr<AstObject> &srcObj)
873 {
874     if (!srcObj->IsArray()) {
875         Logger().Error() << SourceInfo() << "merge conflict type with " << srcObj->SourceInfo();
876         return false;
877     }
878 
879     auto value = srcObj->Child();
880     value->Separate();
881     child_ = value;
882     return true;
883 }
884 
Copy(std::shared_ptr<AstObject> src,bool overwrite)885 bool ConfigArray::Copy(std::shared_ptr<AstObject> src, bool overwrite)
886 {
887     if (!overwrite) {
888         return true;
889     }
890     auto array = ConfigArray::CastFrom(src);
891     child_ = nullptr;
892     auto t = array->child_;
893     while (t != nullptr) {
894         AddChild(AstObjectFactory::Build(t));
895     }
896     return true;
897 }
898 
CastFrom(const std::shared_ptr<AstObject> & astObject)899 ConfigArray *ConfigArray::CastFrom(const std::shared_ptr<AstObject> &astObject)
900 {
901     return static_cast<ConfigArray *>(astObject.get());
902 }
903 
ArraySize() const904 uint16_t ConfigArray::ArraySize() const
905 {
906     return arraySize_;
907 }
908 
ArrayType() const909 uint16_t ConfigArray::ArrayType() const
910 {
911     return arrayType_;
912 }
913 
Build(std::shared_ptr<AstObject> object)914 std::shared_ptr<AstObject> AstObjectFactory::Build(std::shared_ptr<AstObject> object)
915 {
916     switch (object->Type()) {
917         case PARSEROP_CONFNODE:
918             return std::make_shared<ConfigNode>(*ConfigNode::CastFrom(object));
919         case PARSEROP_CONFTERM:
920             return std::make_shared<ConfigTerm>(*ConfigTerm::CastFrom(object));
921         case PARSEROP_ARRAY:
922             return std::make_shared<ConfigArray>(*ConfigArray::CastFrom(object));
923         default:
924             return std::make_shared<AstObject>(*object);
925     }
926 }
927 
Dump(const std::string & prefix)928 void Ast::Dump(const std::string &prefix)
929 {
930     Logger().Debug() << "Dump " << prefix << " AST:";
931     WalkForward([](const std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
932         Logger().Debug() << ::std::setw(walkDepth * FOUR_MULTIPLE) << " " << *current;
933         return NOERR;
934     });
935 }
936 
GetAstRoot()937 std::shared_ptr<AstObject> Ast::GetAstRoot()
938 {
939     return astRoot_;
940 }
941 
Merge(const std::list<std::shared_ptr<Ast>> & astList)942 bool Ast::Merge(const std::list<std::shared_ptr<Ast>> &astList)
943 {
944     if (!RedefineCheck()) {
945         return false;
946     }
947     for (auto &astIt : astList) {
948         if (!astIt->RedefineCheck()) {
949             return false;
950         }
951         if (astRoot_ == nullptr) {
952             astRoot_ = astIt->GetAstRoot();
953             continue;
954         }
955         Dump("merge this");
956         astIt->Dump("tobe merge");
957         if (!astRoot_->Merge(astIt->astRoot_)) {
958             return false;
959         }
960         Dump("merged");
961     }
962     return true;
963 }
964 
Expand()965 bool Ast::Expand()
966 {
967     if (astRoot_->Lookup("module", PARSEROP_CONFTERM) == nullptr) {
968         Logger().Error() << astRoot_->SourceInfo() << "miss 'module' attribute under root node";
969         return false;
970     }
971 
972     if (!NodeExpand()) {
973         return false;
974     }
975 
976     if (!InheritExpand()) {
977         return false;
978     };
979     redefineChecked_ = false;
980     if (!RedefineCheck()) {
981         return false;
982     }
983     Dump("expanded");
984     return true;
985 }
986 
NodeExpandRef()987 bool Ast::NodeExpandRef()
988 {
989     return WalkBackward([this](const std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
990         (void)walkDepth;
991         if (current->IsNode()) {
992             auto node = ConfigNode::CastFrom(current);
993             if (node->GetNodeType() != NODE_REF && node->GetNodeType() != NODE_COPY) {
994                 return NOERR;
995             }
996             // current node maybe deleted after reference expand, never use it after this
997             auto refObject = Lookup(current, node->GetRefPath());
998             if (refObject == nullptr) {
999                 Logger().Error() << node->SourceInfo() << "reference node '" << node->GetRefPath() << "' not exist";
1000                 return EFAIL;
1001             }
1002             if (!refObject->IsNode()) {
1003                 Logger().Error() << node->SourceInfo() << " ref invalid node:" << node->GetRefPath();
1004                 return EFAIL;
1005             }
1006 
1007             auto refNode = ConfigNode::CastFrom(refObject);
1008             if (!refNode->IsBaseNode()) {
1009                 Logger().Error() << "only allow ref base node, " << node->SourceInfo()
1010                                  << " ref invalid node which is not base type: " << node->GetRefPath();
1011                 return EFAIL;
1012             }
1013             if (!node->RefExpand(refObject)) {
1014                 return EFAIL;
1015             }
1016         }
1017         return NOERR;
1018     });
1019 }
1020 
NodeExpandDelete()1021 bool Ast::NodeExpandDelete()
1022 {
1023     return WalkBackward([this](const std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
1024         (void)walkDepth;
1025         if (current->IsNode()) {
1026             auto node = ConfigNode::CastFrom(current);
1027             if (node->GetNodeType() == NODE_DELETE) {
1028                 current->Remove();
1029                 return NOERR;
1030             }
1031         } else if (current->IsTerm()) {
1032             std::shared_ptr<AstObject> ref;
1033             if (current->child_->Type() == PARSEROP_DELETE) {
1034                 current->Remove();
1035                 return NOERR;
1036             }
1037         }
1038         return NOERR;
1039     });
1040 }
1041 
NodeExpandTermRef()1042 bool Ast::NodeExpandTermRef()
1043 {
1044     return WalkBackward([this](const std::shared_ptr<AstObject> &current, int32_t walkDepth) -> int32_t {
1045         (void)walkDepth;
1046         if (!current->IsTerm()) {
1047             return NOERR;
1048         }
1049 
1050         if (current->child_->Type() != PARSEROP_NODEREF) {
1051             return NOERR;
1052         }
1053 
1054         std::shared_ptr<AstObject> ref = Lookup(current, current->child_->StringValue());
1055         if (!ConfigTerm::CastFrom(current)->RefExpand(ref)) {
1056             return EFAIL;
1057         }
1058         return NOERR;
1059     });
1060 }
1061 
NodeExpand()1062 bool Ast::NodeExpand()
1063 {
1064     if (!NodeExpandRef()) {
1065         return false;
1066     }
1067 
1068     if (!NodeExpandDelete()) {
1069         return false;
1070     }
1071 
1072     if (!NodeExpandTermRef()) {
1073         return false;
1074     }
1075     return true;
1076 }
1077 
InheritExpand()1078 bool Ast::InheritExpand()
1079 {
1080     return WalkForward([this](const std::shared_ptr<AstObject> &current, int32_t) -> int32_t {
1081         if (current->IsNode()) {
1082             auto node = ConfigNode::CastFrom(current);
1083             if (node->GetNodeType() != NODE_INHERIT) {
1084                 return NOERR;
1085             }
1086             auto inherit = Lookup(current, node->GetRefPath());
1087             if (!node->InheritExpand(inherit)) {
1088                 return EFAIL;
1089             }
1090         }
1091 
1092         return NOERR;
1093     });
1094 }
1095 
RedefineCheck()1096 bool Ast::RedefineCheck()
1097 {
1098     if (redefineChecked_) {
1099         return true;
1100     }
1101 
1102     bool ret = WalkForward([](const std::shared_ptr<AstObject> &current, int32_t) -> int32_t {
1103         if (current->IsNode() && current->HasDuplicateChild()) {
1104             return EFAIL;
1105         }
1106 
1107         return NOERR;
1108     });
1109 
1110     redefineChecked_ = true;
1111     return ret;
1112 }
1113 
Lookup(const std::shared_ptr<AstObject> & startObj,const std::string & path)1114 std::shared_ptr<AstObject> Ast::Lookup(const std::shared_ptr<AstObject> &startObj, const std::string &path)
1115 {
1116     if (path.find('.') == std::string::npos) {
1117         return startObj->parent_->Lookup(path);
1118     }
1119 
1120     auto splitPath = SplitNodePath(path, '.');
1121     if (splitPath.front() != astRoot_->name_) {
1122         Logger().Error() << "lookup ast with invalid path, which not begin with 'root': " << path;
1123         return nullptr;
1124     }
1125     splitPath.erase(splitPath.begin());
1126 
1127     std::shared_ptr<AstObject> target = astRoot_;
1128     for (auto &it : splitPath) {
1129         // look up children
1130         target = target->Lookup(it);
1131         if (target == nullptr) {
1132             return nullptr;
1133         }
1134     }
1135 
1136     return target;
1137 }
1138 
SplitNodePath(const std::string & path,char separator)1139 std::list<std::string> Ast::SplitNodePath(const std::string &path, char separator)
1140 {
1141     std::list<std::string> splitList;
1142     std::string temp;
1143     for (auto c : path) {
1144         if (c != separator) {
1145             temp.push_back(c);
1146         } else {
1147             if (temp.empty()) {
1148                 splitList.clear();
1149                 break;
1150             }
1151             splitList.push_back(temp);
1152             temp.clear();
1153         }
1154     }
1155 
1156     if (temp.empty()) {
1157         splitList.push_back(path);
1158     } else {
1159         splitList.push_back(temp);
1160     }
1161     return splitList;
1162 }
1163