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; }
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); } }
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; }
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(); }
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; }
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); } }
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(); } }
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; }, {
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; }