svf-lib 1.0.2181 → 1.0.2183
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SVF-linux/Release-build/bin/ae +0 -0
- package/SVF-linux/Release-build/bin/cfl +0 -0
- package/SVF-linux/Release-build/bin/dvf +0 -0
- package/SVF-linux/Release-build/bin/llvm2svf +0 -0
- package/SVF-linux/Release-build/bin/mta +0 -0
- package/SVF-linux/Release-build/bin/saber +0 -0
- package/SVF-linux/Release-build/bin/svf-ex +0 -0
- package/SVF-linux/Release-build/bin/wpa +0 -0
- package/SVF-linux/Release-build/include/SVFIR/SVFIR.h +19 -19
- package/SVF-linux/Release-build/include/SVFIR/SVFVariables.h +12 -12
- package/SVF-linux/Release-build/lib/libSvfCore.a +0 -0
- package/SVF-linux/Release-build/lib/libSvfLLVM.a +0 -0
- package/SVF-osx/Release-build/bin/ae +0 -0
- package/SVF-osx/Release-build/bin/cfl +0 -0
- package/SVF-osx/Release-build/bin/dvf +0 -0
- package/SVF-osx/Release-build/bin/llvm2svf +0 -0
- package/SVF-osx/Release-build/bin/mta +0 -0
- package/SVF-osx/Release-build/bin/saber +0 -0
- package/SVF-osx/Release-build/bin/svf-ex +0 -0
- package/SVF-osx/Release-build/bin/wpa +0 -0
- package/SVF-osx/Release-build/include/DDA/DDAVFSolver.h +5 -7
- package/SVF-osx/Release-build/include/Graphs/ConsG.h +2 -2
- package/SVF-osx/Release-build/include/Graphs/IRGraph.h +5 -18
- package/SVF-osx/Release-build/include/MemoryModel/PointerAnalysis.h +7 -7
- package/SVF-osx/Release-build/include/SVF-LLVM/SymbolTableBuilder.h +2 -2
- package/SVF-osx/Release-build/include/SVFIR/SVFFileSystem.h +0 -12
- package/SVF-osx/Release-build/include/SVFIR/SVFIR.h +84 -106
- package/SVF-osx/Release-build/include/SVFIR/SVFVariables.h +239 -84
- package/SVF-osx/Release-build/include/SVFIR/SymbolTableInfo.h +18 -136
- package/SVF-osx/Release-build/lib/libSvfCore.a +0 -0
- package/SVF-osx/Release-build/lib/libSvfLLVM.a +0 -0
- package/package.json +1 -1
|
@@ -393,15 +393,6 @@ public:
|
|
|
393
393
|
/// return whole allocated memory object if this node is a gep obj node
|
|
394
394
|
/// return nullptr is this node is not a ObjVar type
|
|
395
395
|
//@{
|
|
396
|
-
inline const MemObj* getObject(NodeID id) const
|
|
397
|
-
{
|
|
398
|
-
const SVFVar* node = getGNode(id);
|
|
399
|
-
if (const ObjVar* objPN = SVFUtil::dyn_cast<ObjVar>(node))
|
|
400
|
-
return getObject(objPN);
|
|
401
|
-
else
|
|
402
|
-
return nullptr;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
396
|
inline const BaseObjVar* getBaseObject(NodeID id) const
|
|
406
397
|
{
|
|
407
398
|
const SVFVar* node = getGNode(id);
|
|
@@ -421,20 +412,15 @@ public:
|
|
|
421
412
|
else
|
|
422
413
|
return SVFUtil::dyn_cast<ValVar>(node);
|
|
423
414
|
}
|
|
424
|
-
|
|
425
|
-
inline const MemObj*getObject(const ObjVar* node) const
|
|
426
|
-
{
|
|
427
|
-
return node->getMemObj();
|
|
428
|
-
}
|
|
429
415
|
//@}
|
|
430
416
|
|
|
431
417
|
/// Get a field SVFIR Object node according to base mem obj and offset
|
|
432
|
-
NodeID getGepObjVar(const
|
|
418
|
+
NodeID getGepObjVar(const BaseObjVar* baseObj, const APOffset& ap);
|
|
433
419
|
/// Get a field obj SVFIR node according to a mem obj and a given offset
|
|
434
420
|
NodeID getGepObjVar(NodeID id, const APOffset& ap) ;
|
|
435
421
|
/// Get a field-insensitive obj SVFIR node according to a mem obj
|
|
436
422
|
//@{
|
|
437
|
-
inline NodeID getFIObjVar(const
|
|
423
|
+
inline NodeID getFIObjVar(const BaseObjVar* obj) const
|
|
438
424
|
{
|
|
439
425
|
return obj->getId();
|
|
440
426
|
}
|
|
@@ -464,7 +450,7 @@ public:
|
|
|
464
450
|
}
|
|
465
451
|
inline bool isConstantObj(NodeID id) const
|
|
466
452
|
{
|
|
467
|
-
const
|
|
453
|
+
const BaseObjVar* obj = getBaseObject(id);
|
|
468
454
|
assert(obj && "not an object node?");
|
|
469
455
|
return SymbolTableInfo::isConstantObj(id) ||
|
|
470
456
|
obj->isConstDataOrConstGlobal();
|
|
@@ -476,20 +462,13 @@ public:
|
|
|
476
462
|
/// Get a base pointer node given a field pointer
|
|
477
463
|
inline NodeID getBaseObjVar(NodeID id) const
|
|
478
464
|
{
|
|
479
|
-
return
|
|
480
|
-
}
|
|
481
|
-
inline const MemObj* getBaseObj(NodeID id) const
|
|
482
|
-
{
|
|
483
|
-
const SVFVar* node = pag->getGNode(id);
|
|
484
|
-
assert(SVFUtil::isa<ObjVar>(node) && "need an object node");
|
|
485
|
-
const ObjVar* obj = SVFUtil::cast<ObjVar>(node);
|
|
486
|
-
return obj->getMemObj();
|
|
465
|
+
return getBaseObject(id)->getId();
|
|
487
466
|
}
|
|
488
467
|
//@}
|
|
489
468
|
|
|
490
469
|
/// Get all fields of an object
|
|
491
470
|
//@{
|
|
492
|
-
NodeBS& getAllFieldsObjVars(const
|
|
471
|
+
NodeBS& getAllFieldsObjVars(const BaseObjVar* obj);
|
|
493
472
|
NodeBS& getAllFieldsObjVars(NodeID id);
|
|
494
473
|
NodeBS getFieldsAfterCollapse(NodeID id);
|
|
495
474
|
//@}
|
|
@@ -569,157 +548,152 @@ private:
|
|
|
569
548
|
inline NodeID addValNode(const SVFValue* val, NodeID i, const ICFGNode* icfgNode)
|
|
570
549
|
{
|
|
571
550
|
SVFVar *node = new ValVar(val,i, ValVar::ValNode, icfgNode);
|
|
572
|
-
return addValNode(val, node
|
|
551
|
+
return addValNode(val, node);
|
|
573
552
|
}
|
|
574
553
|
|
|
575
554
|
NodeID addFunValNode(NodeID i, const ICFGNode* icfgNode, const CallGraphNode* callGraphNode)
|
|
576
555
|
{
|
|
577
556
|
FunValVar* node = new FunValVar(i, icfgNode, callGraphNode);
|
|
578
|
-
return addValNode(nullptr, node
|
|
557
|
+
return addValNode(nullptr, node);
|
|
579
558
|
}
|
|
580
559
|
|
|
581
560
|
NodeID addArgValNode(NodeID i, u32_t argNo, const ICFGNode* icfgNode, const CallGraphNode* callGraphNode, bool isUncalled = false)
|
|
582
561
|
{
|
|
583
562
|
ArgValVar* node =
|
|
584
563
|
new ArgValVar(i, argNo, icfgNode, callGraphNode, isUncalled);
|
|
585
|
-
return addValNode(nullptr, node
|
|
564
|
+
return addValNode(nullptr, node);
|
|
586
565
|
}
|
|
587
566
|
|
|
588
567
|
inline NodeID addConstantFPValNode(const SVFValue* curInst, const NodeID i, double dval,
|
|
589
568
|
const ICFGNode* icfgNode)
|
|
590
569
|
{
|
|
591
570
|
SVFVar* node = new ConstantFPValVar(curInst, i, dval, icfgNode);
|
|
592
|
-
return addNode(node
|
|
571
|
+
return addNode(node);
|
|
593
572
|
}
|
|
594
573
|
|
|
595
574
|
inline NodeID addConstantIntValNode(const SVFValue* curInst, NodeID i, const std::pair<s64_t, u64_t>& intValue,
|
|
596
575
|
const ICFGNode* icfgNode)
|
|
597
576
|
{
|
|
598
577
|
SVFVar* node = new ConstantIntValVar(curInst, i, intValue.first, intValue.second, icfgNode);
|
|
599
|
-
return addNode(node
|
|
578
|
+
return addNode(node);
|
|
600
579
|
}
|
|
601
580
|
|
|
602
581
|
inline NodeID addConstantNullPtrValNode(const SVFValue* curInst, const NodeID i, const ICFGNode* icfgNode)
|
|
603
582
|
{
|
|
604
583
|
SVFVar* node = new ConstantNullPtrValVar(curInst, i, icfgNode);
|
|
605
|
-
return addNode(node
|
|
584
|
+
return addNode(node);
|
|
606
585
|
}
|
|
607
586
|
|
|
608
587
|
inline NodeID addGlobalValueValNode(const SVFValue* curInst, const NodeID i, const ICFGNode* icfgNode)
|
|
609
588
|
{
|
|
610
589
|
SVFVar* node = new GlobalValVar(curInst, i, icfgNode);
|
|
611
|
-
return addNode(node
|
|
590
|
+
return addNode(node);
|
|
612
591
|
}
|
|
613
592
|
|
|
614
593
|
inline NodeID addConstantDataValNode(const SVFValue* curInst, const NodeID i, const ICFGNode* icfgNode)
|
|
615
594
|
{
|
|
616
595
|
SVFVar* node = new ConstantDataValVar(curInst, i, icfgNode);
|
|
617
|
-
return addNode(node
|
|
596
|
+
return addNode(node);
|
|
618
597
|
}
|
|
619
598
|
|
|
620
599
|
|
|
621
600
|
/// Add a memory obj node
|
|
622
|
-
inline NodeID addObjNode(const SVFValue* val, NodeID i)
|
|
601
|
+
inline NodeID addObjNode(const SVFValue* val, NodeID i, ObjTypeInfo* ti)
|
|
623
602
|
{
|
|
624
|
-
|
|
625
|
-
assert(mem->getId() == i && "not same object id?");
|
|
626
|
-
return addFIObjNode(mem);
|
|
603
|
+
return addFIObjNode(val, i, ti);
|
|
627
604
|
}
|
|
628
605
|
|
|
629
606
|
/**
|
|
630
607
|
* Creates and adds a heap object node to the SVFIR
|
|
631
608
|
*/
|
|
632
|
-
inline NodeID addHeapObjNode(const SVFValue* val, NodeID i, const SVFFunction* f)
|
|
609
|
+
inline NodeID addHeapObjNode(const SVFValue* val, NodeID i, ObjTypeInfo* ti, const SVFFunction* f)
|
|
633
610
|
{
|
|
634
|
-
const MemObj* mem = getMemObj(val);
|
|
635
|
-
assert(mem->getId() == i && "not same object id?");
|
|
636
611
|
memToFieldsMap[i].set(i);
|
|
637
|
-
HeapObjVar *
|
|
638
|
-
return addObjNode(val,
|
|
612
|
+
HeapObjVar *heapObj = new HeapObjVar(val, i, ti, f);
|
|
613
|
+
return addObjNode(val, heapObj);
|
|
639
614
|
}
|
|
640
615
|
|
|
641
616
|
/**
|
|
642
617
|
* Creates and adds a stack object node to the SVFIR
|
|
643
618
|
*/
|
|
644
|
-
inline NodeID addStackObjNode(const SVFValue* val, NodeID i, const SVFFunction* f)
|
|
619
|
+
inline NodeID addStackObjNode(const SVFValue* val, NodeID i, ObjTypeInfo* ti, const SVFFunction* f)
|
|
645
620
|
{
|
|
646
|
-
const MemObj* mem = getMemObj(val);
|
|
647
|
-
assert(mem->getId() == i && "not same object id?");
|
|
648
621
|
memToFieldsMap[i].set(i);
|
|
649
|
-
StackObjVar *
|
|
650
|
-
return addObjNode(val,
|
|
622
|
+
StackObjVar *stackObj = new StackObjVar(val, i, ti, f);
|
|
623
|
+
return addObjNode(val, stackObj);
|
|
651
624
|
}
|
|
652
625
|
|
|
653
|
-
NodeID addFunObjNode(NodeID id, const CallGraphNode* callGraphNode)
|
|
626
|
+
NodeID addFunObjNode(const SVFValue* val, NodeID id, ObjTypeInfo* ti, const CallGraphNode* callGraphNode)
|
|
627
|
+
{
|
|
628
|
+
memToFieldsMap[id].set(id);
|
|
629
|
+
FunObjVar* funObj = new FunObjVar(val, id, ti, callGraphNode);
|
|
630
|
+
return addObjNode(val, funObj);
|
|
631
|
+
}
|
|
654
632
|
|
|
655
633
|
|
|
656
|
-
inline NodeID addConstantFPObjNode(const SVFValue* curInst, NodeID i, double dval)
|
|
634
|
+
inline NodeID addConstantFPObjNode(const SVFValue* curInst, NodeID i, ObjTypeInfo* ti, double dval)
|
|
657
635
|
{
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
ConstantFPObjVar* node = new ConstantFPObjVar(curInst, i, dval, mem);
|
|
662
|
-
return addObjNode(curInst, node, mem->getId());
|
|
636
|
+
memToFieldsMap[i].set(i);
|
|
637
|
+
ConstantFPObjVar* conObj = new ConstantFPObjVar(curInst, i, dval, ti);
|
|
638
|
+
return addObjNode(curInst, conObj);
|
|
663
639
|
}
|
|
664
640
|
|
|
665
641
|
|
|
666
|
-
inline NodeID addConstantIntObjNode(const SVFValue* curInst, NodeID i, const std::pair<s64_t, u64_t>& intValue)
|
|
642
|
+
inline NodeID addConstantIntObjNode(const SVFValue* curInst, NodeID i, ObjTypeInfo* ti, const std::pair<s64_t, u64_t>& intValue)
|
|
667
643
|
{
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
new ConstantIntObjVar(curInst, i, intValue.first, intValue.second, mem);
|
|
673
|
-
return addObjNode(curInst, node, mem->getId());
|
|
644
|
+
memToFieldsMap[i].set(i);
|
|
645
|
+
ConstantIntObjVar* conObj =
|
|
646
|
+
new ConstantIntObjVar(curInst, i, intValue.first, intValue.second, ti);
|
|
647
|
+
return addObjNode(curInst, conObj);
|
|
674
648
|
}
|
|
675
649
|
|
|
676
650
|
|
|
677
|
-
inline NodeID addConstantNullPtrObjNode(const SVFValue* curInst, const NodeID i)
|
|
651
|
+
inline NodeID addConstantNullPtrObjNode(const SVFValue* curInst, const NodeID i, ObjTypeInfo* ti)
|
|
678
652
|
{
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
ConstantNullPtrObjVar* node = new ConstantNullPtrObjVar(curInst, mem->getId(), mem);
|
|
683
|
-
return addObjNode(mem->getValue(), node, mem->getId());
|
|
653
|
+
memToFieldsMap[i].set(i);
|
|
654
|
+
ConstantNullPtrObjVar* conObj = new ConstantNullPtrObjVar(curInst, i, ti);
|
|
655
|
+
return addObjNode(curInst, conObj);
|
|
684
656
|
}
|
|
685
657
|
|
|
686
|
-
inline NodeID addGlobalValueObjNode(const SVFValue* curInst, const NodeID i)
|
|
658
|
+
inline NodeID addGlobalValueObjNode(const SVFValue* curInst, const NodeID i, ObjTypeInfo* ti)
|
|
687
659
|
{
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
GlobalObjVar* node = new GlobalObjVar(curInst, mem->getId(), mem);
|
|
692
|
-
return addObjNode(mem->getValue(), node, mem->getId());
|
|
660
|
+
memToFieldsMap[i].set(i);
|
|
661
|
+
GlobalObjVar* gObj = new GlobalObjVar(curInst, i, ti);
|
|
662
|
+
return addObjNode(curInst, gObj);
|
|
693
663
|
}
|
|
694
664
|
|
|
695
|
-
inline NodeID addConstantDataObjNode(const SVFValue* curInst, const NodeID i)
|
|
665
|
+
inline NodeID addConstantDataObjNode(const SVFValue* curInst, const NodeID i, ObjTypeInfo* ti)
|
|
696
666
|
{
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
ConstantDataObjVar* node = new ConstantDataObjVar(curInst, mem->getId(), mem);
|
|
701
|
-
return addObjNode(mem->getValue(), node, mem->getId());
|
|
667
|
+
memToFieldsMap[i].set(i);
|
|
668
|
+
ConstantDataObjVar* conObj = new ConstantDataObjVar(curInst, i, ti);
|
|
669
|
+
return addObjNode(curInst, conObj);
|
|
702
670
|
}
|
|
703
671
|
|
|
704
672
|
/// Add a unique return node for a procedure
|
|
705
673
|
inline NodeID addRetNode(NodeID i, const CallGraphNode* callGraphNode)
|
|
706
674
|
{
|
|
707
675
|
SVFVar *node = new RetPN(i, callGraphNode);
|
|
708
|
-
return addRetNode(callGraphNode, node
|
|
676
|
+
return addRetNode(callGraphNode, node);
|
|
709
677
|
}
|
|
710
678
|
/// Add a unique vararg node for a procedure
|
|
711
679
|
inline NodeID addVarargNode(NodeID i, const CallGraphNode* val)
|
|
712
680
|
{
|
|
713
681
|
SVFVar *node = new VarArgPN(i, val);
|
|
714
|
-
return addNode(node
|
|
682
|
+
return addNode(node);
|
|
715
683
|
}
|
|
716
684
|
|
|
717
685
|
/// Add a temp field value node, this method can only invoked by getGepValVar
|
|
718
686
|
NodeID addGepValNode(const SVFValue* curInst,const SVFValue* val, const AccessPath& ap, NodeID i, const SVFType* type);
|
|
719
687
|
/// Add a field obj node, this method can only invoked by getGepObjVar
|
|
720
|
-
NodeID addGepObjNode(const
|
|
688
|
+
NodeID addGepObjNode(const BaseObjVar* baseObj, const APOffset& apOffset, const NodeID gepId);
|
|
721
689
|
/// Add a field-insensitive node, this method can only invoked by getFIGepObjNode
|
|
722
|
-
NodeID addFIObjNode(const
|
|
690
|
+
NodeID addFIObjNode(const SVFValue* val, NodeID i, ObjTypeInfo* ti)
|
|
691
|
+
{
|
|
692
|
+
memToFieldsMap[i].set(i);
|
|
693
|
+
BaseObjVar* baseObj = new BaseObjVar(val, i, ti);
|
|
694
|
+
return addObjNode(val, baseObj);
|
|
695
|
+
}
|
|
696
|
+
|
|
723
697
|
|
|
724
698
|
//@}
|
|
725
699
|
|
|
@@ -727,28 +701,30 @@ private:
|
|
|
727
701
|
//@{
|
|
728
702
|
inline NodeID addDummyValNode(NodeID i)
|
|
729
703
|
{
|
|
730
|
-
return addValNode(nullptr, new DummyValVar(i)
|
|
704
|
+
return addValNode(nullptr, new DummyValVar(i));
|
|
731
705
|
}
|
|
732
706
|
inline NodeID addDummyObjNode(NodeID i, const SVFType* type)
|
|
733
707
|
{
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
708
|
+
if (symInfo->idToObjTypeInfoMap().find(i) == symInfo->idToObjTypeInfoMap().end())
|
|
709
|
+
{
|
|
710
|
+
ObjTypeInfo* ti = symInfo->createObjTypeInfo(type);
|
|
711
|
+
symInfo->idToObjTypeInfoMap()[i] = ti;
|
|
712
|
+
return addObjNode(nullptr, new DummyObjVar(i, ti));
|
|
713
|
+
}
|
|
714
|
+
else
|
|
715
|
+
{
|
|
716
|
+
return addObjNode(nullptr, new DummyObjVar(i, symInfo->getObjTypeInfo(i)));
|
|
717
|
+
}
|
|
740
718
|
}
|
|
719
|
+
|
|
741
720
|
inline NodeID addBlackholeObjNode()
|
|
742
721
|
{
|
|
743
722
|
return addObjNode(
|
|
744
|
-
nullptr, new DummyObjVar(getBlackHoleNode(),
|
|
745
|
-
getBlackHoleNode());
|
|
723
|
+
nullptr, new DummyObjVar(getBlackHoleNode(), symInfo->getObjTypeInfo(getBlackHoleNode())));
|
|
746
724
|
}
|
|
747
725
|
inline NodeID addConstantObjNode()
|
|
748
726
|
{
|
|
749
|
-
return addObjNode(nullptr,
|
|
750
|
-
new DummyObjVar(getConstantNode(), getConstantObj()),
|
|
751
|
-
getConstantNode());
|
|
727
|
+
return addObjNode(nullptr, new DummyObjVar(getConstantNode(), symInfo->getObjTypeInfo(getConstantNode())));
|
|
752
728
|
}
|
|
753
729
|
inline NodeID addBlackholePtrNode()
|
|
754
730
|
{
|
|
@@ -757,30 +733,32 @@ private:
|
|
|
757
733
|
//@}
|
|
758
734
|
|
|
759
735
|
/// Add a value (pointer) node
|
|
760
|
-
inline NodeID addValNode(const SVFValue*, SVFVar *node
|
|
736
|
+
inline NodeID addValNode(const SVFValue*, SVFVar *node)
|
|
761
737
|
{
|
|
762
|
-
assert(
|
|
738
|
+
assert(node && "node cannot be nullptr.");
|
|
739
|
+
assert(hasGNode(node->getId()) == false &&
|
|
763
740
|
"This NodeID clashes here. Please check NodeIDAllocator. Switch "
|
|
764
741
|
"Strategy::DBUG to SEQ or DENSE");
|
|
765
|
-
return addNode(node
|
|
742
|
+
return addNode(node);
|
|
766
743
|
}
|
|
767
744
|
/// Add a memory obj node
|
|
768
|
-
inline NodeID addObjNode(const SVFValue*, SVFVar *node
|
|
745
|
+
inline NodeID addObjNode(const SVFValue*, SVFVar *node)
|
|
769
746
|
{
|
|
770
|
-
assert(
|
|
747
|
+
assert(node && "node cannot be nullptr.");
|
|
748
|
+
assert(hasGNode(node->getId()) == false &&
|
|
771
749
|
"This NodeID clashes here. Please check NodeIDAllocator. Switch "
|
|
772
750
|
"Strategy::DBUG to SEQ or DENSE");
|
|
773
|
-
return addNode(node
|
|
751
|
+
return addNode(node);
|
|
774
752
|
}
|
|
775
753
|
/// Add a unique return node for a procedure
|
|
776
|
-
inline NodeID addRetNode(const CallGraphNode*, SVFVar *node
|
|
754
|
+
inline NodeID addRetNode(const CallGraphNode*, SVFVar *node)
|
|
777
755
|
{
|
|
778
|
-
return addNode(node
|
|
756
|
+
return addNode(node);
|
|
779
757
|
}
|
|
780
758
|
/// Add a unique vararg node for a procedure
|
|
781
|
-
inline NodeID addVarargNode(const SVFFunction*, SVFVar *node
|
|
759
|
+
inline NodeID addVarargNode(const SVFFunction*, SVFVar *node)
|
|
782
760
|
{
|
|
783
|
-
return addNode(node
|
|
761
|
+
return addNode(node);
|
|
784
762
|
}
|
|
785
763
|
|
|
786
764
|
/// Add global PAGEdges (not in a procedure)
|