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> ¤t, 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> ¤t, 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> ¤t, 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> ¤t, 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> ¤t, 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> ¤t, 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