コード例 #1
0
 bool DepthFirstOrder::check()
 {
     // check that post(v) is consistent with post()
       std::size_t r = 0;
        for (std::size_t v : PostOrder()) {
            if (Post(v) != r) {
                std::cout<<"post(v) and post() inconsistent"<<std::endl;
                return false;
            }
            r++;
        }

        // check that pre(v) is consistent with pre()
        r = 0;
        for (std::size_t v : PreOrder()) {
            if (Pre(v) != r) {
                std::cout<<"post(v) and post() inconsistent"<<std::endl;
                 return false;
            }
            r++;
        }


        return true;
    }
コード例 #2
0
main() {
    Pre();
    int rs,time,n;
    char x[110];
    scanf("%d",&time); getchar();
    for (int t=1;t<=time;t++) {
        gets(x); rs=0; n=strlen(x);
        for (int i=0;i<n;i++) rs+=a[x[i]];
        printf("Case #%d: %d\n",t,rs);
    }
}
コード例 #3
0
ファイル: main.cpp プロジェクト: telamonian/stocuda
int main () {
	matrix<std::string> P(2,1);
	matrix<std::string> T(2,1);
	matrix<int> Pre(2,2);
	matrix<int> Post(2,2);
	matrix<int> M(2,1);
	state_type c(2,1);

	P(0,0) = "U"; P(1,0) = "U2";
	T(0,0) = "Dimerisation"; T(1,0) = "Dissociation";
	Pre(0,0) = 2; Pre(0,1) = 0; Pre(1,0) = 0; Pre(1,1) = 1;
	Post(0,0) = 0; Post(0,1) = 2; Post(1,0) = 1; Post(1,1) = 0;
	M(0,0) = 1000; M(1,0) = 0;
	c(0,0) = 1.0; c(1,0) = .5;
	Pnet N(P, T, Pre, Post, M, c);
	std::cout << "time" << '\t' << "marking" << std::endl;
	std::cout << N.t << '\t' << N.M << std::endl;
	N.Gillespie(10000);
	return 0;
}
コード例 #4
0
ファイル: ngiter.cpp プロジェクト: UIKit0/xara-xtreme
BOOL NodeScan::Scan()
{
	// Call Pre() before the scan.
	if (!Pre()) return FALSE;

	// Perform the appropriate type of scan.
	for (Node* pNode = m_pSource->GetFirst();
		 pNode != 0;
		 pNode = m_pSource->GetNext(pNode))
	{
		// NB. Post() not called if scan fails.
		if (!Do(pNode)) return FALSE;
	}

	// Call Post() after a successful scan.
	return Post();
}
コード例 #5
0
ファイル: Main.cpp プロジェクト: hzsunzixiang/programming
int main()
{
	BinaryTree <int>  BTT;
	BTT.input();
	LevelOrder<int> Level(BTT);
	//Level.Traverse();
	PostOrder<int> Post(BTT);
	//Post.Traverse();
	InOrder<int> In(BTT);
	//In.Traverse();
	PreOrder<int> Pre(BTT);
	//Pre.Traverse();
    cout<<"******************************"<<endl;   
	cout<<"*selet an item        "<<endl;
	cout<<"*levelorder traverse,enter'1' "   <<endl;
	cout<<"*preorder traverse,enter '2'  "<<endl;
	cout<<"*inorder traverse enter '3'    "<<endl;
    cout<<"*postorder traverse enter '3'    "<<endl;	
	cout<<"*quit,enter  '0'          "<<endl;
	cout<<"******************************"<<endl;
	int i;	
	
	do
	{   cin>>i;  
		cout<<"ÇëÊäÈëÄãµÄÑ¡Ôñ£º";
		cout<<"1---> levelorder traverse¡¢2----preorder traverse¡¢3----inorder traverse¡¢4--->postorder traverse¡¢0--->quit¡¢"<<endl;

	   switch(i)
	   { 
	      case 1:	  	
               Level.Traverse();        
			   break;
		   case 2: 	   	
               Pre.Traverse();
			   break;
		   case 3:	  
               In.Traverse();
			    break;
		   case 4:   
               Post.Traverse();
			   break;
	   }		   
	   }while(i!=0);
	return 1;
}
コード例 #6
0
main()
{
  //  freopen("127inp.txt","r",stdin);
  //  freopen("127out.txt","w",stdout);
    int time=0;
    scanf("%d",&n);
    while (n!=0)
    {
        count=0;
        scanf("%s",&a);
        Pre();
        if (num==1)
        {
            if (Check_if_free(n-1)) count++;
        }
        else BR(1);
        printf("Case %d: %d\n",++time,count);
        scanf("%d",&n);
    }
}
コード例 #7
0
ファイル: parse.cpp プロジェクト: Ambrevar/fr_public
void ParseCondBlock(sInt *elsemod,sBool useelse)
{
  sInt mod;
  sBool kill,always;

  kill = always = sFALSE;

  if(!useelse)
  {
    mod = Modify++;
    if(elsemod)
      *elsemod = Modify++;
  }
  else
    mod = *elsemod;

  if(elsemod && Mode==2)
  {
    if(!useelse)
    {
      kill = !ModArray[*elsemod - 1];
      always = !ModArray[*elsemod];
    }
    else
    {
      kill = !ModArray[*elsemod];
      always = !ModArray[*elsemod - 1];
    }
  }

  Pre();
  if(kill || always)
  {
    OutBOpen();
    OutBClose();
    NewLine();
    if(kill)
      OutF("if(0)");
    else
      OutF("if(1)");
  }

  if(Token==TOK_BOPEN)
  {
    MatchBOpen();
    sInt ind = Indent;
    BeginIf(mod);
    sInt ind2 = Indent;

    while(Token!=TOK_BCLOSE)
    {
      ParseStatement();
    }

    sVERIFY(Indent == ind2);
    EndIf(mod);
    sVERIFY(Indent == ind);
    MatchBClose();
  }
  else
  {
    OutBOpen();
    BeginIf(mod);

    ParseStatement();

    EndIf(mod);
    OutBClose();
  }
}
コード例 #8
0
ファイル: Relooper.cpp プロジェクト: Edinunzio/emscripten
void Relooper::Calculate(Block *Entry) {
  // Scan and optimize the input
  struct PreOptimizer : public RelooperRecursor {
    PreOptimizer(Relooper *Parent) : RelooperRecursor(Parent) {}
    BlockSet Live;

    void FindLive(Block *Root) {
      BlockList ToInvestigate;
      ToInvestigate.push_back(Root);
      while (ToInvestigate.size() > 0) {
        Block *Curr = ToInvestigate.front();
        ToInvestigate.pop_front();
        if (Live.find(Curr) != Live.end()) continue;
        Live.insert(Curr);
        for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
          ToInvestigate.push_back(iter->first);
        }
      }
    }

    // If a block has multiple entries but no exits, and it is small enough, it is useful to split it.
    // A common example is a C++ function where everything ends up at a final exit block and does some
    // RAII cleanup. Without splitting, we will be forced to introduce labelled loops to allow
    // reaching the final block
    void SplitDeadEnds() {
      int TotalCodeSize = 0;
      for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) {
        Block *Curr = *iter;
        TotalCodeSize += strlen(Curr->Code);
      }

      for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) {
        Block *Original = *iter;
        if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue;
        if (strlen(Original->Code)*(Original->BranchesIn.size()-1) > TotalCodeSize/5) continue; // if splitting increases raw code size by a significant amount, abort
        // Split the node (for simplicity, we replace all the blocks, even though we could have reused the original)
        for (BlockBranchMap::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) {
          Block *Prior = iter->first;
          Block *Split = new Block(Original->Code);
          Split->BranchesIn[Prior] = new Branch(NULL);
          Prior->BranchesOut[Split] = new Branch(Prior->BranchesOut[Original]->Condition, Prior->BranchesOut[Original]->Code);
          Prior->BranchesOut.erase(Original);
          Parent->AddBlock(Split);
          Live.insert(Split);
        }
      }
    }
  };
  PreOptimizer Pre(this);
  Pre.FindLive(Entry);

  // Add incoming branches from live blocks, ignoring dead code
  for (int i = 0; i < Blocks.size(); i++) {
    Block *Curr = Blocks[i];
    if (Pre.Live.find(Curr) == Pre.Live.end()) continue;
    for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
      iter->first->BranchesIn[Curr] = new Branch(NULL);
    }
  }

  Pre.SplitDeadEnds();

  // Recursively process the graph

  struct Analyzer : public RelooperRecursor {
    Analyzer(Relooper *Parent) : RelooperRecursor(Parent) {}

    // Add a shape to the list of shapes in this Relooper calculation
    void Notice(Shape *New) {
      Parent->Shapes.push_back(New);
    }

    // Create a list of entries from a block. If LimitTo is provided, only results in that set
    // will appear
    void GetBlocksOut(Block *Source, BlockSet& Entries, BlockSet *LimitTo=NULL) {
      for (BlockBranchMap::iterator iter = Source->BranchesOut.begin(); iter != Source->BranchesOut.end(); iter++) {
        if (!LimitTo || LimitTo->find(iter->first) != LimitTo->end()) {
          Entries.insert(iter->first);
        }
      }
    }

    // Converts/processes all branchings to a specific target
    void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, BlockSet &From) {
      PrintDebug("Solipsizing branches into %d\n", Target->Id);
      DebugDump(From, "  relevant to solipsize: ");
      for (BlockBranchMap::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) {
        Block *Prior = iter->first;
        if (From.find(Prior) == From.end()) {
          iter++;
          continue;
        }
        Branch *TargetIn = iter->second;
        Branch *PriorOut = Prior->BranchesOut[Target];
        PriorOut->Ancestor = Ancestor; // Do we need this info
        PriorOut->Type = Type;         // on TargetIn too?
        if (MultipleShape *Multiple = Shape::IsMultiple(Ancestor)) {
          Multiple->NeedLoop++; // We are breaking out of this Multiple, so need a loop
        }
        iter++; // carefully increment iter before erasing
        Target->BranchesIn.erase(Prior);
        Target->ProcessedBranchesIn[Prior] = TargetIn;
        Prior->BranchesOut.erase(Target);
        Prior->ProcessedBranchesOut[Target] = PriorOut;
        PrintDebug("  eliminated branch from %d\n", Prior->Id);
      }
    }

    Shape *MakeSimple(BlockSet &Blocks, Block *Inner, BlockSet &NextEntries) {
      PrintDebug("creating simple block with block #%d\n", Inner->Id);
      SimpleShape *Simple = new SimpleShape;
      Notice(Simple);
      Simple->Inner = Inner;
      Inner->Parent = Simple;
      if (Blocks.size() > 1) {
        Blocks.erase(Inner);
        GetBlocksOut(Inner, NextEntries, &Blocks);
        BlockSet JustInner;
        JustInner.insert(Inner);
        for (BlockSet::iterator iter = NextEntries.begin(); iter != NextEntries.end(); iter++) {
          Solipsize(*iter, Branch::Direct, Simple, JustInner);
        }
      }
      return Simple;
    }

    Shape *MakeLoop(BlockSet &Blocks, BlockSet& Entries, BlockSet &NextEntries) {
      // Find the inner blocks in this loop. Proceed backwards from the entries until
      // you reach a seen block, collecting as you go.
      BlockSet InnerBlocks;
      BlockSet Queue = Entries;
      while (Queue.size() > 0) {
        Block *Curr = *(Queue.begin());
        Queue.erase(Queue.begin());
        if (InnerBlocks.find(Curr) == InnerBlocks.end()) {
          // This element is new, mark it as inner and remove from outer
          InnerBlocks.insert(Curr);
          Blocks.erase(Curr);
          // Add the elements prior to it
          for (BlockBranchMap::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) {
            Queue.insert(iter->first);
          }
        }
      }
      assert(InnerBlocks.size() > 0);

      for (BlockSet::iterator iter = InnerBlocks.begin(); iter != InnerBlocks.end(); iter++) {
        Block *Curr = *iter;
        for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
          Block *Possible = iter->first;
          if (InnerBlocks.find(Possible) == InnerBlocks.end() &&
              NextEntries.find(Possible) == NextEntries.find(Possible)) {
            NextEntries.insert(Possible);
          }
        }
      }

      PrintDebug("creating loop block:\n");
      DebugDump(InnerBlocks, "  inner blocks:");
      DebugDump(Entries, "  inner entries:");
      DebugDump(Blocks, "  outer blocks:");
      DebugDump(NextEntries, "  outer entries:");

      // TODO: Optionally hoist additional blocks into the loop

      LoopShape *Loop = new LoopShape();
      Notice(Loop);

      // Solipsize the loop, replacing with break/continue and marking branches as Processed (will not affect later calculations)
      // A. Branches to the loop entries become a continue to this shape
      for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) {
        Solipsize(*iter, Branch::Continue, Loop, InnerBlocks);
      }
      // B. Branches to outside the loop (a next entry) become breaks on this shape
      for (BlockSet::iterator iter = NextEntries.begin(); iter != NextEntries.end(); iter++) {
        Solipsize(*iter, Branch::Break, Loop, InnerBlocks);
      }
      // Finish up
      Shape *Inner = Process(InnerBlocks, Entries, NULL);
      Loop->Inner = Inner;
      return Loop;
    }

    // For each entry, find the independent group reachable by it. The independent group is
    // the entry itself, plus all the blocks it can reach that cannot be directly reached by another entry. Note that we
    // ignore directly reaching the entry itself by another entry.
    void FindIndependentGroups(BlockSet &Blocks, BlockSet &Entries, BlockBlockSetMap& IndependentGroups) {
      typedef std::map<Block*, Block*> BlockBlockMap;

      struct HelperClass {
        BlockBlockSetMap& IndependentGroups;
        BlockBlockMap Ownership; // For each block, which entry it belongs to. We have reached it from there.

        HelperClass(BlockBlockSetMap& IndependentGroupsInit) : IndependentGroups(IndependentGroupsInit) {}
        void InvalidateWithChildren(Block *New) { // TODO: rename New
          BlockList ToInvalidate; // Being in the list means you need to be invalidated
          ToInvalidate.push_back(New);
          while (ToInvalidate.size() > 0) {
            Block *Invalidatee = ToInvalidate.front();
            ToInvalidate.pop_front();
            Block *Owner = Ownership[Invalidatee];
            if (IndependentGroups.find(Owner) != IndependentGroups.end()) { // Owner may have been invalidated, do not add to IndependentGroups!
              IndependentGroups[Owner].erase(Invalidatee);
            }
            if (Ownership[Invalidatee]) { // may have been seen before and invalidated already
              Ownership[Invalidatee] = NULL;
              for (BlockBranchMap::iterator iter = Invalidatee->BranchesOut.begin(); iter != Invalidatee->BranchesOut.end(); iter++) {
                Block *Target = iter->first;
                BlockBlockMap::iterator Known = Ownership.find(Target);
                if (Known != Ownership.end()) {
                  Block *TargetOwner = Known->second;
                  if (TargetOwner) {
                    ToInvalidate.push_back(Target);
                  }
                }
              }
            }
          }
        }
      };
      HelperClass Helper(IndependentGroups);

      // We flow out from each of the entries, simultaneously.
      // When we reach a new block, we add it as belonging to the one we got to it from.
      // If we reach a new block that is already marked as belonging to someone, it is reachable by
      // two entries and is not valid for any of them. Remove it and all it can reach that have been
      // visited.

      BlockList Queue; // Being in the queue means we just added this item, and we need to add its children
      for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) {
        Block *Entry = *iter;
        Helper.Ownership[Entry] = Entry;
        IndependentGroups[Entry].insert(Entry);
        Queue.push_back(Entry);
      }
      while (Queue.size() > 0) {
        Block *Curr = Queue.front();
        Queue.pop_front();
        Block *Owner = Helper.Ownership[Curr]; // Curr must be in the ownership map if we are in the queue
        if (!Owner) continue; // we have been invalidated meanwhile after being reached from two entries
        // Add all children
        for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
          Block *New = iter->first;
          BlockBlockMap::iterator Known = Helper.Ownership.find(New);
          if (Known == Helper.Ownership.end()) {
            // New node. Add it, and put it in the queue
            Helper.Ownership[New] = Owner;
            IndependentGroups[Owner].insert(New);
            Queue.push_back(New);
            continue;
          }
          Block *NewOwner = Known->second;
          if (!NewOwner) continue; // We reached an invalidated node
          if (NewOwner != Owner) {
            // Invalidate this and all reachable that we have seen - we reached this from two locations
            Helper.InvalidateWithChildren(New);
          }
          // otherwise, we have the same owner, so do nothing
        }
      }

      // Having processed all the interesting blocks, we remain with just one potential issue:
      // If a->b, and a was invalidated, but then b was later reached by someone else, we must
      // invalidate b. To check for this, we go over all elements in the independent groups,
      // if an element has a parent which does *not* have the same owner, we must remove it
      // and all its children.

      for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) {
        BlockSet &CurrGroup = IndependentGroups[*iter];
        BlockList ToInvalidate;
        for (BlockSet::iterator iter = CurrGroup.begin(); iter != CurrGroup.end(); iter++) {
          Block *Child = *iter;
          for (BlockBranchMap::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) {
            Block *Parent = iter->first;
            if (Helper.Ownership[Parent] != Helper.Ownership[Child]) {
              ToInvalidate.push_back(Child);
            }
          }
        }
        while (ToInvalidate.size() > 0) {
          Block *Invalidatee = ToInvalidate.front();
          ToInvalidate.pop_front();
          Helper.InvalidateWithChildren(Invalidatee);
        }
      }

      // Remove empty groups
      for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) {
        if (IndependentGroups[*iter].size() == 0) {
          IndependentGroups.erase(*iter);
        }
      }

#if DEBUG
      PrintDebug("Investigated independent groups:\n");
      for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) {
        DebugDump(iter->second, " group: ");
      }
#endif
    }

    Shape *MakeMultiple(BlockSet &Blocks, BlockSet& Entries, BlockBlockSetMap& IndependentGroups, Shape *Prev, BlockSet &NextEntries) {
      PrintDebug("creating multiple block with %d inner groups\n", IndependentGroups.size());
      bool Fused = !!(Shape::IsSimple(Prev));
      MultipleShape *Multiple = new MultipleShape();
      Notice(Multiple);
      BlockSet CurrEntries;
      for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end(); iter++) {
        Block *CurrEntry = iter->first;
        BlockSet &CurrBlocks = iter->second;
        PrintDebug("  multiple group with entry %d:\n", CurrEntry->Id);
        DebugDump(CurrBlocks, "    ");
        // Create inner block
        CurrEntries.clear();
        CurrEntries.insert(CurrEntry);
        for (BlockSet::iterator iter = CurrBlocks.begin(); iter != CurrBlocks.end(); iter++) {
          Block *CurrInner = *iter;
          // Remove the block from the remaining blocks
          Blocks.erase(CurrInner);
          // Find new next entries and fix branches to them
          for (BlockBranchMap::iterator iter = CurrInner->BranchesOut.begin(); iter != CurrInner->BranchesOut.end();) {
            Block *CurrTarget = iter->first;
            BlockBranchMap::iterator Next = iter;
            Next++;
            if (CurrBlocks.find(CurrTarget) == CurrBlocks.end()) {
              NextEntries.insert(CurrTarget);
              Solipsize(CurrTarget, Branch::Break, Multiple, CurrBlocks); 
            }
            iter = Next; // increment carefully because Solipsize can remove us
          }
        }
        Multiple->InnerMap[CurrEntry] = Process(CurrBlocks, CurrEntries, NULL);
        // If we are not fused, then our entries will actually be checked
        if (!Fused) {
          CurrEntry->IsCheckedMultipleEntry = true;
        }
      }
      DebugDump(Blocks, "  remaining blocks after multiple:");
      // Add entries not handled as next entries, they are deferred
      for (BlockSet::iterator iter = Entries.begin(); iter != Entries.end(); iter++) {
        Block *Entry = *iter;
        if (IndependentGroups.find(Entry) == IndependentGroups.end()) {
          NextEntries.insert(Entry);
        }
      }
      return Multiple;
    }

    // Main function.
    // Process a set of blocks with specified entries, returns a shape
    // The Make* functions receive a NextEntries. If they fill it with data, those are the entries for the
    //   ->Next block on them, and the blocks are what remains in Blocks (which Make* modify). In this way
    //   we avoid recursing on Next (imagine a long chain of Simples, if we recursed we could blow the stack).
    Shape *Process(BlockSet &Blocks, BlockSet& InitialEntries, Shape *Prev) {
      PrintDebug("Process() called\n");
      BlockSet *Entries = &InitialEntries;
      BlockSet TempEntries[2];
      int CurrTempIndex = 0;
      BlockSet *NextEntries;
      Shape *Ret = NULL;
      #define Make(call) \
        Shape *Temp = call; \
        if (Prev) Prev->Next = Temp; \
        if (!Ret) Ret = Temp; \
        if (!NextEntries->size()) { PrintDebug("Process() returning\n"); return Ret; } \
        Prev = Temp; \
        Entries = NextEntries; \
        continue;
      while (1) {
        PrintDebug("Process() running\n");
        DebugDump(Blocks, "  blocks : ");
        DebugDump(*Entries, "  entries: ");

        CurrTempIndex = 1-CurrTempIndex;
        NextEntries = &TempEntries[CurrTempIndex];
        NextEntries->clear();

        if (Entries->size() == 0) return Ret;
        if (Entries->size() == 1) {
          Block *Curr = *(Entries->begin());
          if (Curr->BranchesIn.size() == 0) {
            // One entry, no looping ==> Simple
            Make(MakeSimple(Blocks, Curr, *NextEntries));
          }
          // One entry, looping ==> Loop
          Make(MakeLoop(Blocks, *Entries, *NextEntries));
        }
        // More than one entry, try to eliminate through a Multiple groups of
        // independent blocks from an entry/ies. It is important to remove through
        // multiples as opposed to looping since the former is more performant.
        BlockBlockSetMap IndependentGroups;
        FindIndependentGroups(Blocks, *Entries, IndependentGroups);

        PrintDebug("Independent groups: %d\n", IndependentGroups.size());

        if (IndependentGroups.size() > 0) {
          // We can handle a group in a multiple if its entry cannot be reached by another group.
          // Note that it might be reachable by itself - a loop. But that is fine, we will create
          // a loop inside the multiple block (which is the performant order to do it).
          for (BlockBlockSetMap::iterator iter = IndependentGroups.begin(); iter != IndependentGroups.end();) {
            Block *Entry = iter->first;
            BlockSet &Group = iter->second;
            BlockBlockSetMap::iterator curr = iter++; // iterate carefully, we may delete
            for (BlockBranchMap::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) {
              Block *Origin = iterBranch->first;
              if (Group.find(Origin) == Group.end()) {
                // Reached from outside the group, so we cannot handle this
                PrintDebug("Cannot handle group with entry %d because of incoming branch from %d\n", Entry->Id, Origin->Id);
                IndependentGroups.erase(curr);
                break;
              }
            }
          }

          // As an optimization, if we have 2 independent groups, and one is a small dead end, we can handle only that dead end.
          // The other then becomes a Next - without nesting in the code and recursion in the analysis.
          // TODO: if the larger is the only dead end, handle that too
          // TODO: handle >2 groups
          // TODO: handle not just dead ends, but also that do not branch to the NextEntries. However, must be careful
          //       there since we create a Next, and that Next can prevent eliminating a break (since we no longer
          //       naturally reach the same place), which may necessitate a one-time loop, which makes the unnesting
          //       pointless.
          if (IndependentGroups.size() == 2) {
            // Find the smaller one
            BlockBlockSetMap::iterator iter = IndependentGroups.begin();
            Block *SmallEntry = iter->first;
            int SmallSize = iter->second.size();
            iter++;
            Block *LargeEntry = iter->first;
            int LargeSize = iter->second.size();
            if (SmallSize != LargeSize) { // ignore the case where they are identical - keep things symmetrical there
              if (SmallSize > LargeSize) {
                Block *Temp = SmallEntry;
                SmallEntry = LargeEntry;
                LargeEntry = Temp; // Note: we did not flip the Sizes too, they are now invalid. TODO: use the smaller size as a limit?
              }
              // Check if dead end
              bool DeadEnd = true;
              BlockSet &SmallGroup = IndependentGroups[SmallEntry];
              for (BlockSet::iterator iter = SmallGroup.begin(); iter != SmallGroup.end(); iter++) {
                Block *Curr = *iter;
                for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) {
                  Block *Target = iter->first;
                  if (SmallGroup.find(Target) == SmallGroup.end()) {
                    DeadEnd = false;
                    break;
                  }
                }
                if (!DeadEnd) break;
              }
              if (DeadEnd) {
                PrintDebug("Removing nesting by not handling large group because small group is dead end\n");
                IndependentGroups.erase(LargeEntry);
              }
            }
          }

          PrintDebug("Handleable independent groups: %d\n", IndependentGroups.size());

          if (IndependentGroups.size() > 0) {
            // Some groups removable ==> Multiple
            Make(MakeMultiple(Blocks, *Entries, IndependentGroups, Prev, *NextEntries));
          }
        }
        // No independent groups, must be loopable ==> Loop
        Make(MakeLoop(Blocks, *Entries, *NextEntries));
      }
    }
  };

  // Main

  BlockSet AllBlocks;
  for (int i = 0; i < Blocks.size(); i++) {
    AllBlocks.insert(Blocks[i]);
#if DEBUG
    PrintDebug("Adding block %d (%s)\n", Blocks[i]->Id, Blocks[i]->Code);
    for (BlockBranchMap::iterator iter = Blocks[i]->BranchesOut.begin(); iter != Blocks[i]->BranchesOut.end(); iter++) {
      PrintDebug("  with branch out to %d\n", iter->first->Id);
    }
#endif
  }

  BlockSet Entries;
  Entries.insert(Entry);
  Root = Analyzer(this).Process(AllBlocks, Entries, NULL);

  // Post optimizations

  struct PostOptimizer {
    Relooper *Parent;
    void *Closure;

    PostOptimizer(Relooper *ParentInit) : Parent(ParentInit), Closure(NULL) {}

    #define RECURSE_MULTIPLE_MANUAL(func, manual) \
      for (BlockShapeMap::iterator iter = manual->InnerMap.begin(); iter != manual->InnerMap.end(); iter++) { \
        func(iter->second); \
      }
    #define RECURSE_MULTIPLE(func) RECURSE_MULTIPLE_MANUAL(func, Multiple);
    #define RECURSE_LOOP(func) \
      func(Loop->Inner);

    #define SHAPE_SWITCH(var, simple, multiple, loop) \
      if (SimpleShape *Simple = Shape::IsSimple(var)) { \
        simple; \
      } else if (MultipleShape *Multiple = Shape::IsMultiple(var)) { \
        multiple; \
      } else if (LoopShape *Loop = Shape::IsLoop(var)) { \
        loop; \
      }

    #define SHAPE_SWITCH_AUTO(var, simple, multiple, loop, func) \
      if (SimpleShape *Simple = Shape::IsSimple(var)) { \
        simple; \
        func(Simple->Next); \
      } else if (MultipleShape *Multiple = Shape::IsMultiple(var)) { \
        multiple; \
        RECURSE_MULTIPLE(func) \
        func(Multiple->Next); \
      } else if (LoopShape *Loop = Shape::IsLoop(var)) { \
        loop; \
        RECURSE_LOOP(func); \
        func(Loop->Next); \
      }

    // Remove unneeded breaks and continues.
    // A flow operation is trivially unneeded if the shape we naturally get to by normal code
    // execution is the same as the flow forces us to.
    void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) {
      Shape *Next = Root;
      while (Next) {
        Root = Next;
        Next = NULL;
        SHAPE_SWITCH(Root, {
          // If there is a next block, we already know at Simple creation time to make direct branches,
          // and we can do nothing more. If there is no next however, then Natural is where we will
          // go to by doing nothing, so we can potentially optimize some branches to direct.
          if (Simple->Next) {
            Next = Simple->Next;
          } else {
            for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) {
              Block *Target = iter->first;
              Branch *Details = iter->second;
              if (Details->Type != Branch::Direct && Target->Parent == Natural) {
                Details->Type = Branch::Direct;
                if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) {
                  Multiple->NeedLoop--;
                }
              }
            }
          }
        }, {
          for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) {
            RemoveUnneededFlows(iter->second, Multiple->Next);
          }
          Next = Multiple->Next;
        }, {
コード例 #9
0
int main()
{
	Copyright();  //输出程序信息

	char *s = (char *)malloc(MAXLEN * sizeof(char));         //用来保存输入数据
	char *backups_s = s;                                     //备份s指针 用于释放内存
    char *filepath = (char *)malloc(MAXLEN * sizeof(char));  //用来储存文件路径
	char *backups_p = filepath;
	while (1)
	{
        Pre();
		s = backups_s;
		Read_Argv(s);
		if (*s != '-')
		{
			gets(s);
			Error();
			continue;
		}
		s ++;
		filepath = backups_p;
        
		if (Equal(s , "index"))
		{
		    int t;
			scanf("%d" , &t);
			if (t == 1)
			    printf("---Open the index function successfully.---\n");
			else
				if (t == 0)
					printf("---Close the index function successfully.---\n");
				else
					Error();
			gets(s);
			continue;
		}
		else
			if (*(s + 1) != '\0')
			{
				gets(s);
				Error();
				continue;
			}
		switch (*s) 
		{
		    case 'c' : Get_Path(filepath);
				       Create_Table(filepath);
					   break;

			case 'i' : s = backups_s;   
					   Get_Table(s);        //第二个参数 表名
				       Get_Path(filepath);
					   Import_Data(s , filepath);
					   break;

			case 's' : Get_Path(filepath);
					   Select(filepath);
					   break;

			case 'u' : Get_Path(filepath);
					   Update(filepath);
				       break;

			case 'd' : Get_Path(filepath);
					   Delete(filepath);
					   break;

			case 'h' : Help();
				       break;

		    case 'q' : Exit_pro();
					   free(backups_s);
					   free(backups_p);
					   Free();
				       return 0;

			default  : gets(s);
				       Error();
				       break;
		}
		gets(s);
	}

	return 0;
}