Пример #1
0
// Start solving the problem.
bool Board::Unblock(Blocks bs)
{
    count_setblock = 0;
    count_checkblock = 0;
    count_setcell = 0;
    count_checkcell = 0;

    // Sort Blocks by block weight
    sort(bs.begin(), bs.end(), [](Block *a, Block *b)
    {
        return (a->weight > b->weight);
    });

    for (auto i = bs.cbegin(); i != bs.cend(); i++)
    {
        (*i)->Print("Block " + to_string(i - bs.cbegin()));
    }

    // Find solution
    bool result = RecursiveSetBlock(bs, 0);

    cout << "count_setblock   = " << count_setblock << endl
         << "count_checkblock = " << count_checkblock << endl
         << "count_setcell    = " << count_setcell << endl
         << "count_checkcell  = " << count_checkcell << endl;

    return result;
}
Пример #2
0
 ~CFGCalculator() {
   for(Blocks::iterator i = blocks_.begin();
       i != blocks_.end();
       i++) {
     delete i->second;
   }
 }
Пример #3
0
void PatchMgr::getBlockCandidates(Scope &scope, Point::Type types, Candidates &ret) {
   Blocks blocks;
   getBlocks(scope, blocks);
   for (Blocks::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
      if (types & Point::BlockEntry) ret.push_back(Candidate(Location::Block(*iter), Point::BlockEntry));
      if (types & Point::BlockDuring) ret.push_back(Candidate(Location::Block(*iter), Point::BlockDuring));
      if (types & Point::BlockExit) ret.push_back(Candidate(Location::Block(*iter), Point::BlockExit));
   }
}
Пример #4
0
void PatchMgr::getInsns(Scope &scope, Insns &insns) {
   Blocks blocks;
   getBlocks(scope, blocks);

   for (Blocks::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) {
      PatchBlock::Insns tmp;
      (*iter)->getInsns(tmp);
      for (PatchBlock::Insns::iterator t = tmp.begin(); t != tmp.end(); ++t) {
         insns.push_back(InsnLoc_t(*iter, t->first, t->second));
      }
   }
}
Пример #5
0
void findDeadBlockEdges(Blocks &blocks) {
	/* Run through all blocks and find edges that are logically dead and will
	 * never be taken.
	 *
	 * Currently, this is limited to one special case that occurs in scripts
	 * compiled by the original BioWare NWScript compiler (at least in NWN and
	 * KotOR): short-circuiting in if (x || y) conditionals. The original BioWare
	 * compiler has a bug where it generates a JZ instead of a JMP, creating a
	 * true branch that will never be taken and effectively disabling short-
	 * circuiting. I.e. both x and y will always be evaluated; when x is true,
	 * y will still be evaluated afterwards.
	 *
	 * We use very simple pattern-matching here. This is enough to find most
	 * occurances of this case, but not all. */

	for (Blocks::iterator b = blocks.begin(); b != blocks.end(); ++b) {
		if (!isTopStackJumper(*b) || (b->instructions.size() != 2) || b->parents.empty())
			continue;

		/* Look through all parents of this block and make sure they fit the
		 * pattern as well. They also all need to jump to this block with the
		 * same branch edge (true or false). */
		size_t parentEdge = SIZE_MAX;
		for (std::vector<const Block *>::const_iterator p = b->parents.begin(); p != b->parents.end(); ++p) {
			if (!isTopStackJumper(**p, &*b, &parentEdge)) {
				parentEdge = SIZE_MAX;
				break;
			}
		}
		if (parentEdge == SIZE_MAX)
			continue;

		assert(parentEdge < 2);

		/* We have now established that
		 * 1) This block checks whether the top of the stack is == 0
		 * 2) All parent blocks check whether the top of the stack is == 0
		 * 3) All parent blocks jump with the same branch edge into this block
		 *
		 * Therefore, this block must also always follow the exact same edge.
		 * This means the other edge is logically dead. */

		b->childrenTypes[1 - parentEdge] = kBlockEdgeTypeDead;
	}
}
Пример #6
0
	bool IsBlockFree( const SBlock& p_Block )const
	{
		unsigned int unRight = p_Block.m_unLeft + p_Block.m_unWidth;
		unsigned int unBottom = p_Block.m_unTop + p_Block.m_unHeight;

		if( unRight > m_unWidth || unBottom > m_unHeight )
		{
			return false;
		}

		Blocks::const_iterator IteEnd = m_vecBlocks.end();
		for( Blocks::const_iterator Ite = m_vecBlocks.begin();
			Ite != IteEnd; ++Ite )
		{
			if( Ite->m_unLeft < unRight && p_Block.m_unLeft < Ite->m_unLeft + Ite->m_unWidth 
				&& Ite->m_unTop < unBottom && p_Block.m_unTop < Ite->m_unTop + Ite->m_unHeight )
			{
				return false;
			}
		}
		return true;
	}
Пример #7
0
void findDeadBlockEdges(Blocks &blocks) {
	/* Run through all blocks and find edges that are logically dead and will
	 * never be taken.
	 *
	 * Currently, this is limited to one special case that occurs in scripts
	 * compiled by the original BioWare NWScript compiler (at least in NWN and
	 * KotOR): short-circuiting in if (x || y) conditionals. The original BioWare
	 * compiler has a bug where it generates a JZ instead of a JMP, creating a
	 * true branch that will never be taken and effectively disabling short-
	 * circuiting. I.e. both x and y will always be evaluated; when x is true,
	 * y will still be evaluated afterwards.
	 *
	 * We use very simple pattern-matching here. This is enough to find most
	 * occurrences of this case, but not all.
	 *
	 * For example, this is the control flow diagram for the bytecode, as
	 * compiled by the original BioWare compiler, for
	 *
	 * if ((global_variable == 1) || (global_variable == 3))
	 *
	 *        .
	 *        |
	 *        V
	 * .-------------------.
	 * | CPTOPBP -4 4      |
	 * | CONSTI 1          |
	 * | EQII              |
	 * | CPTOPSP -4 4      |
	 * | JZ                |
	 * '-------------------'
	 *  (true)|    |(false)
	 *        |    V (1)
	 *        | .--------------------.
	 *        | | CPTOPSP -4 4       |
	 *        | | JZ                 | (4)
	 *        | '--------------------'
	 *        |  (false)|     |(true)
	 *        |    (2)  |     |  (3)
	 *        V         V     |
	 * .-------------------.  |
	 * | CPTOPBP -4 4      |  |
	 * | CONSTI 3          |  |
	 * | EQII              |  |
	 * '-------------------'  |
	 *         |              |
	 *         V              |
	 * .-------------------.  |
	 * | LOGORII -4 4      |  |
	 * | JZ                |<-'
	 * '-------------------'
	 *  (true) |   |(false)
	 *         '   '
	 *
	 * "CPTOPSP -4 4" takes the top element on the stack and, without
	 * popping it, pushes it again onto the top, creating a duplicate.
	 *
	 * When taking the false branch at (1) (which means that the variable
	 * *is* equal to 1), we have already established that the top element
	 * on the stack (which is getting copied a few times, so it's not
	 * vanishing) is of a certain value. This means that the false branch
	 * at (2) has to be taken as well. The true branch at (3) can't ever
	 * be taken, and is therefore logically dead.
	 *
	 * Moreover, if the true branch at (3) would have been taken, this
	 * had resulted in a stack smash, because JZ consumes a stack element,
	 * and the LOGORII would now be one element short.
	 *
	 * Essentially, the whole block at (4) evaluates to a NOP.
	 *
	 * How this *should* have been compiled is thusly:
	 *
	 *        .
	 *        |
	 *        V
	 * .-------------------.
	 * | CPTOPBP -4 4      |
	 * | CONSTI 1          |
	 * | EQII              |
	 * | CPTOPSP -4 4      |
	 * | JZ                |
	 * '-------------------'
	 *  (true)|    |(false)
	 *        |    V
	 *        | .--------------------.
	 *        | | CPTOPSP -4 4       | (5)
	 *        | | JMP                |
	 *        | '--------------------'
	 *        |               |
	 *        |               |
	 *        V               |
	 * .-------------------.  |
	 * | CPTOPBP -4 4      |  |
	 * | CONSTI 3          |  |
	 * | EQII              |  |
	 * '-------------------'  |
	 *         |              |
	 *         V      (6)     |
	 * .-------------------.  |
	 * | LOGORII -4 4      |  |
	 * | JZ                |<-'
	 * '-------------------'
	 *  (true) |   |(false)
	 *         '   '
	 *
	 * In the block at (5), the top element is now copied, and the code
	 * jumps unconditionally to the LOGORII block at (6). In contrast
	 * to JZ, JMP does not pop an element from the stack. The LOGORII
	 * has enough elements to do its comparison.
	 *
	 * This is exactly what the OpenKnights compiler does. And this has
	 * been fixed by BioWare by the time of Neverwinter Nights 2 as well.
	 *
	 * The short-circuiting && construct does not seem to have this fault.
	 */

	for (Blocks::iterator b = blocks.begin(); b != blocks.end(); ++b) {
		if (!isTopStackJumper(*b) || (b->instructions.size() != 2) || b->parents.empty())
			continue;

		/* Look through all parents of this block and make sure they fit the
		 * pattern as well. They also all need to jump to this block with the
		 * same branch edge (true or false). */
		size_t parentEdge = SIZE_MAX;
		for (std::vector<const Block *>::const_iterator p = b->parents.begin(); p != b->parents.end(); ++p) {
			if (!isTopStackJumper(**p, &*b, &parentEdge)) {
				parentEdge = SIZE_MAX;
				break;
			}
		}
		if (parentEdge == SIZE_MAX)
			continue;

		assert(parentEdge < 2);

		/* We have now established that
		 * 1) This block checks whether the top of the stack is == 0
		 * 2) All parent blocks check whether the top of the stack is == 0
		 * 3) All parent blocks jump with the same branch edge into this block
		 *
		 * Therefore, this block must also always follow the exact same edge.
		 * This means the other edge is logically dead. */

		b->childrenTypes[1 - parentEdge] = kBlockEdgeTypeDead;
	}
}
Пример #8
0
BlkModel::BlkModel(const BlkModel& rhs) {
	Blocks blocks = const_cast<BlkModel&>(rhs).blocks();
	for (Blocks::iterator it = blocks.begin(); it != blocks.end(); ++it)
		addBlock(it->first, it->second);
}
Пример #9
0
 CFGBlock* find_block(int ip) {
   Blocks::iterator i = blocks_.find(ip);
   if(i == blocks_.end()) return 0;
   return i->second;
 }
Пример #10
0
void AbstractAligner::change_blocks_impl(Blocks& blocks) const {
    std::sort(blocks.begin(), blocks.end(), BlockSquareLess());
}
Пример #11
0
/**
* Unpause par2-files
* returns true, if the files with required number of blocks were unpaused,
* or false if there are no more files in queue for this collection or not enough blocks.
* special case: returns true if there are any unpaused par2-files in the queue regardless
* of the amount of blocks; this is to keep par-checker wait for download completion.
*/
bool ParCoordinator::RequestMorePars(NZBInfo* pNZBInfo, const char* szParFilename, int iBlockNeeded, int* pBlockFound)
{
	DownloadQueue* pDownloadQueue = DownloadQueue::Lock();
	
	Blocks blocks;
	blocks.clear();
	int iBlockFound = 0;
    int iCurBlockFound = 0;

	FindPars(pDownloadQueue, pNZBInfo, szParFilename, &blocks, true, true, &iCurBlockFound);
    iBlockFound += iCurBlockFound;
	if (iBlockFound < iBlockNeeded)
	{
		FindPars(pDownloadQueue, pNZBInfo, szParFilename, &blocks, true, false, &iCurBlockFound);
        iBlockFound += iCurBlockFound;
	}
	if (iBlockFound < iBlockNeeded)
	{
		FindPars(pDownloadQueue, pNZBInfo, szParFilename, &blocks, false, false, &iCurBlockFound);
        iBlockFound += iCurBlockFound;
	}

	if (iBlockFound >= iBlockNeeded)
	{
		// 1. first unpause all files with par-blocks less or equal iBlockNeeded
		// starting from the file with max block count.
		// if par-collection was built exponentially and all par-files present,
		// this step selects par-files with exact number of blocks we need.
		while (iBlockNeeded > 0)
		{               
			BlockInfo* pBestBlockInfo = NULL;
			for (Blocks::iterator it = blocks.begin(); it != blocks.end(); it++)
			{
				BlockInfo* pBlockInfo = *it;
				if (pBlockInfo->m_iBlockCount <= iBlockNeeded &&
				   (!pBestBlockInfo || pBestBlockInfo->m_iBlockCount < pBlockInfo->m_iBlockCount))
				{
					pBestBlockInfo = pBlockInfo;
				}
			}
			if (pBestBlockInfo)
			{
				if (pBestBlockInfo->m_pFileInfo->GetPaused())
				{
					m_ParChecker.PrintMessage(Message::mkInfo, "Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBestBlockInfo->m_pFileInfo->GetFilename());
					pBestBlockInfo->m_pFileInfo->SetPaused(false);
					pBestBlockInfo->m_pFileInfo->SetExtraPriority(true);
				}
				iBlockNeeded -= pBestBlockInfo->m_iBlockCount;
				blocks.remove(pBestBlockInfo);
				delete pBestBlockInfo;
			}
			else
			{
				break;
			}
		}
			
		// 2. then unpause other files
		// this step only needed if the par-collection was built not exponentially 
		// or not all par-files present (or some of them were corrupted)
		// this step is not optimal, but we hope, that the first step will work good 
		// in most cases and we will not need the second step often
		while (iBlockNeeded > 0)
		{
			BlockInfo* pBlockInfo = blocks.front();
			if (pBlockInfo->m_pFileInfo->GetPaused())
			{
				m_ParChecker.PrintMessage(Message::mkInfo, "Unpausing %s%c%s for par-recovery", pNZBInfo->GetName(), (int)PATH_SEPARATOR, pBlockInfo->m_pFileInfo->GetFilename());
				pBlockInfo->m_pFileInfo->SetPaused(false);
				pBlockInfo->m_pFileInfo->SetExtraPriority(true);
			}
			iBlockNeeded -= pBlockInfo->m_iBlockCount;
		}
	}

	bool bHasUnpausedParFiles = false;
	for (FileList::iterator it = pNZBInfo->GetFileList()->begin(); it != pNZBInfo->GetFileList()->end(); it++)
	{
		FileInfo* pFileInfo = *it;
		if (pFileInfo->GetParFile() && !pFileInfo->GetPaused())
		{
			bHasUnpausedParFiles = true;
			break;
		}
	}

	DownloadQueue::Unlock();

	if (pBlockFound)
	{
		*pBlockFound = iBlockFound;
	}

	for (Blocks::iterator it = blocks.begin(); it != blocks.end(); it++)
	{
		delete *it;
	}
	blocks.clear();

	bool bOK = iBlockNeeded <= 0 || bHasUnpausedParFiles;

	return bOK;
}