CLiveInOutCalculator::CLiveInOutCalculator( const std::list<const CBaseInstruction*>& asmFunction ) :
		workflow( asmFunction ), liveIn( workflow.Size() ), liveOut( workflow.Size() )
	{
		bool setsChanged = true;
		int mainFuncIndex = 0;
		std::vector<int> revTopsort = CTopSort::topSort( workflow, mainFuncIndex );
		buildCommands( asmFunction );
		buildDefines( asmFunction );
		buildUses( asmFunction );

		std::reverse( revTopsort.begin(), revTopsort.end() );
		while( setsChanged ) {
			setsChanged = false;
			for( auto nodeIndex : revTopsort ) {
				std::set<std::string> newLiveIn = liveOut[nodeIndex];
				auto currList = commands[nodeIndex]->DefinedVars();
				while( currList != nullptr  &&  currList->Head() != nullptr ) {
					auto inSet = newLiveIn.find( currList->Head()->GetName()->GetString() );
					if( inSet != newLiveIn.end() ) {
						newLiveIn.erase( inSet );
					}
					currList = currList->Tail();
				}
				currList = commands[nodeIndex]->UsedVars();
				while( currList != nullptr  &&  currList->Head() != nullptr ) {
					newLiveIn.insert( currList->Head()->GetName()->GetString() );
					currList = currList->Tail();
				}
				std::set<std::string> newLiveOut;
				for( auto succ : workflow.GetNode( nodeIndex ).out ) {
					for( auto var : liveIn[succ] ) {
						newLiveOut.insert( var );
					}
				}
				if( !theSame( newLiveIn, liveIn[nodeIndex] ) || !theSame( newLiveOut, liveOut[nodeIndex] ) ) {
					setsChanged = true;
					liveIn[nodeIndex] = newLiveIn;
					liveOut[nodeIndex] = newLiveOut;
				}
			}
		}
	}
bool executeExternalCommand(char * firstArg) {

    LinkedList<char *> * tokens = new LinkedList<char *>(firstArg);

    tokenizeString(tokens);

    if(!validateCommand(tokens))
        return false;

    LinkedList<Command *> * commands = new LinkedList<Command *>();

    if(!buildCommands(tokens, commands))
        return false;

    if(!executeCommands(commands))
        return false;

    delete tokens;

    return true;
}