bool PolicyCompiler_pf::createTables::processNext()
{
    PolicyCompiler_pf *pf_comp = dynamic_cast<PolicyCompiler_pf*>(compiler);
    PolicyRule *rule = getNext(); if (rule==NULL) return false;

    RuleElementSrc *src = rule->getSrc();
    RuleElementDst *dst = rule->getDst();

    if (!src->isAny()) pf_comp->tables->createTablesForRE(src, rule);
    if (!dst->isAny()) pf_comp->tables->createTablesForRE(dst, rule);

    tmp_queue.push_back(rule);
    return true;
}
bool PolicyCompiler_pf::splitIfFirewallInSrc::processNext()
{
    PolicyRule *rule=getNext(); if (rule==NULL) return false;

    PolicyRule *r;
    RuleElementSrc *src = rule->getSrc();
    assert(src);

    if (src->size()==1 || src->getNeg())
    {
	tmp_queue.push_back(rule);
	return true;
    }

    FWObject *fw_in_src = NULL;
    vector<FWObject*> cl;
    for (FWObject::iterator i1=src->begin(); i1!=src->end(); ++i1)
    {
	FWObject *obj = FWReference::getObject(*i1);
	if (obj==NULL)
            compiler->abort(rule, "Broken Src object");

	if (obj->getId()==compiler->getFwId())
        {
	    fw_in_src = obj;

	    RuleElementSrc *nsrc;

	    r = compiler->dbcopy->createPolicyRule();
	    compiler->temp_ruleset->add(r);
	    r->duplicate(rule);
	    nsrc = r->getSrc();
	    nsrc->clearChildren();
	    nsrc->setAnyElement();
	    nsrc->addRef( compiler->fw );
	    tmp_queue.push_back(r);
	}
    }
    if (fw_in_src!=NULL) src->removeRef( fw_in_src );

    tmp_queue.push_back(rule);
    return true;
}
bool PolicyCompiler_ipf::doSrcNegation::processNext()
{
    PolicyRule *rule=getNext(); if (rule==NULL) return false;

    RuleElementSrc *src=rule->getSrc();

    if (src->getNeg()) {
        RuleElementSrc *nsrc;
	PolicyRule     *r;
        FWOptions *ruleopt;

	r= compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	r->setAction(PolicyRule::Continue);
	r->setLogging(false);
        nsrc=r->getSrc();
        nsrc->setNeg(false);
	r->setBool("quick",false);
        r->setBool("skip_check_for_duplicates",true);
        ruleopt = r->getOptionsObject();
        ruleopt->setBool("stateless", true);
	tmp_queue.push_back(r);

	r= compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
        nsrc=r->getSrc();
        nsrc->setNeg(false);
	nsrc->clearChildren();
	nsrc->setAnyElement();
	r->setBool("quick",true);
        r->setBool("skip_check_for_duplicates",true);
	tmp_queue.push_back(r);

	return true;
    }
    tmp_queue.push_back(rule);
    return true;
}
bool PolicyCompiler_pf::doSrcNegation::processNext()
{
    PolicyRule *rule=getNext(); if (rule==NULL) return false;

    RuleElementSrc *src=rule->getSrc();

    if (src->getNeg()) {
        RuleElementSrc *nsrc;
	PolicyRule     *r;

	r= compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
	if (rule->getAction()==PolicyRule::Accept)
            r->setAction(PolicyRule::Deny);
	else
            r->setAction(PolicyRule::Accept);
        nsrc=r->getSrc();
        nsrc->setNeg(false);
	r->setBool("quick",true);
        r->setLogging(false);
	tmp_queue.push_back(r);

	r= compiler->dbcopy->createPolicyRule();
	compiler->temp_ruleset->add(r);
	r->duplicate(rule);
        nsrc=r->getSrc();
        nsrc->setNeg(false);
	nsrc->clearChildren();
	nsrc->setAnyElement();
	r->setBool("quick",true);
	tmp_queue.push_back(r);

	return true;
    }
    tmp_queue.push_back(rule);
    return true;
}
string PolicyCompiler::debugPrintRule(Rule *r)
{
    PolicyRule *rule=PolicyRule::cast(r);

//    FWOptions *ruleopt =rule->getOptionsObject();

    RuleElementSrc *srcrel = rule->getSrc();
    RuleElementDst *dstrel = rule->getDst();
    RuleElementSrv *srvrel = rule->getSrv();
    RuleElementItf *itfrel = rule->getItf();

//    int iface_id = rule->getInterfaceId();
//    Interface *rule_iface = Interface::cast(dbcopy->findInIndex(iface_id));

    ostringstream str;

//    str << setw(70) << setfill('-') << "-";

    int no=0;
    FWObject::iterator i1=srcrel->begin();
    FWObject::iterator i2=dstrel->begin(); 
    FWObject::iterator i3=srvrel->begin();
    FWObject::iterator i4=itfrel->begin();

    while ( i1!=srcrel->end() || i2!=dstrel->end() || i3!=srvrel->end() ||
            i4!=itfrel->end())
    {
        str << endl;

        string src=" ";
        string dst=" ";
        string srv=" ";
        string itf=" ";

        int src_id = -1;
        int dst_id = -1;
        int srv_id = -1;

        if (srcrel->getNeg()) src = "!";
        if (dstrel->getNeg()) dst = "!";
        if (srvrel->getNeg()) srv = "!";
        if (itfrel->getNeg()) itf = "!";

        if (i1!=srcrel->end())
        {
            FWObject *o = FWReference::getObject(*i1);
            src += o->getName();
            src_id = o->getId();
        }

        if (i2!=dstrel->end())
        {
            FWObject *o = FWReference::getObject(*i2);
            dst += o->getName();
            dst_id = o->getId();
        }

        if (i3!=srvrel->end())
        {
            FWObject *o = FWReference::getObject(*i3);
            srv += o->getName();
            srv_id = o->getId();
        }

        if (i4!=itfrel->end())
        {
            ostringstream str;
            FWObject *o = FWReference::getObject(*i4);
            str << o->getName() << "(" << o->getId() << ")";
            itf += str.str();
        }

        int w = 0;
        if (no==0)
        {
            str << rule->getLabel();
            w = rule->getLabel().length();
        }
        
        str <<  setw(10-w)  << setfill(' ') << " ";

        str <<  setw(18) << setfill(' ') << src.c_str() << "(" << src_id << ")";
        str <<  setw(18) << setfill(' ') << dst.c_str() << "(" << dst_id << ")";
        str <<  setw(12) << setfill(' ') << srv.c_str() << "(" << srv_id << ")";
        str <<  setw(8)  << setfill(' ') << itf.c_str();

        if (no==0)
        {
            str <<  setw(9)  << setfill(' ') << rule->getActionAsString().c_str();
            str <<  setw(12)  << setfill(' ') << rule->getDirectionAsString().c_str();
            if (rule->getLogging()) str << " LOG";
        } else
            str <<  setw(18)  << setfill(' ') << " ";

        ++no;

        if ( i1!=srcrel->end() ) ++i1;
        if ( i2!=dstrel->end() ) ++i2;
        if ( i3!=srvrel->end() ) ++i3;
        if ( i4!=itfrel->end() ) ++i4;
    }
    return str.str();
}
bool PolicyCompiler_pix::matchTranslatedAddresses::processNext()
{
    PolicyRule *rule = getNext(); if (rule==nullptr) return false;

    string version = compiler->fw->getStr("version");

    transformed_rules.clear();

    RuleElementSrc *srcrel = rule->getSrc();
    RuleElementDst *dstrel = rule->getDst();
    RuleElementSrv *srvrel = rule->getSrv();

    for (list<FWObject*>::iterator i1=srcrel->begin(); i1!=srcrel->end(); ++i1) 
    {
        for (list<FWObject*>::iterator i2=dstrel->begin(); i2!=dstrel->end(); ++i2) 
        {
            for (list<FWObject*>::iterator i3=srvrel->begin(); i3!=srvrel->end(); ++i3) 
            {
                FWObject *o1  = *i1;
                FWObject *o2  = *i2;
                FWObject *o3  = *i3;
                FWObject *obj1 = nullptr;
                FWObject *obj2 = nullptr;
                FWObject *obj3 = nullptr;

                obj1 = FWReference::getObject(o1);
                Address *src = Address::cast(obj1);
                assert(src!=nullptr);

                obj2 = FWReference::getObject(o2);
                Address *dst = Address::cast(obj2);
                assert(dst!=nullptr);

                obj3 = FWReference::getObject(o3);
                Service *srv = Service::cast(obj3);
                assert(srv!=nullptr);

                list<NATRule*> tl = findMatchingNATRules(src, dst, srv);

                for( list<NATRule*>::iterator t=tl.begin(); t!=tl.end(); ++t)
                    action(rule, *t, src, dst, srv);

            }
        }
    }
/*
 *list transformed_rules has all the atomic rules that have a matching
 * NAT rule, with dst and srv already converted. We just add them to
 * the policy on top of the original rule.
 */
    list<PolicyRule*>::iterator i1;
    for (i1=transformed_rules.begin(); i1!=transformed_rules.end(); ++i1)
    {
        PolicyRule *r=PolicyRule::cast( *i1 );
        tmp_queue.push_back(r);
    }

    tmp_queue.push_back(rule);

    return true;
}
void PolicyCompiler_pix::replaceTranslatedAddresses::action(
    PolicyRule* policy_rule,
    NATRule* nat_rule, Address *src, Address*, Service *srv)
{

//    FWObject *rule_iface = compiler->dbcopy->findInIndex(
//        policy_rule->getInterfaceId());

    RuleElementItf *intf_re = policy_rule->getItf();
    FWObject *rule_iface = FWObjectReference::getObject(intf_re->front());

    RuleElement *re = nat_rule->getOSrc();

    FWObject *o = FWReference::getObject(re->front());
#ifndef NDEBUG
    Address  *osrc = Address::cast(o); assert(osrc);
#endif

    re = nat_rule->getODst();
    o = FWReference::getObject(re->front());
    Address  *odst = Address::cast(o); assert(odst);

    re = nat_rule->getOSrv();
    o = FWReference::getObject(re->front());
    Service  *osrv = Service::cast(o); assert(osrv);

#ifndef NDEBUG
    re = nat_rule->getTSrc();
    o = FWReference::getObject(re->front());
    Address  *tsrc = Address::cast(o); assert(tsrc);

    re = nat_rule->getTDst();
    o = FWReference::getObject(re->front());
    Address  *tdst = Address::cast(o); assert(tdst);

    re = nat_rule->getTSrv();
    o = FWReference::getObject(re->front());
    Service  *tsrv = Service::cast(o); assert(tsrv);
#endif

    FWObject *p = odst->getParent();

    if (odst->getId() == rule_iface->getId() ||
        p->getId() == rule_iface->getId())
    {

        PolicyRule  *r = compiler->dbcopy->createPolicyRule();
        compiler->temp_ruleset->add(r);
        r->duplicate(policy_rule);

        RuleElementSrc *nsrc = r->getSrc();
        nsrc->clearChildren();
        nsrc->addRef( src );

        RuleElementDst *ndst = r->getDst();
        ndst->clearChildren();
        ndst->addRef( odst );

        RuleElementSrv *nsrv = r->getSrv();
        nsrv->clearChildren();

        if (osrv->isAny())
            nsrv->addRef( srv );
        else
            nsrv->addRef( osrv );

        transformed_rules.push_back(r);
    }

}