static int bc_zone_generate(int codep, bytecode_info_t *retval,
                            int zonetag, const char *zone)
{
        unsigned hours;
        unsigned minutes;
        char sign;

        assert(retval != NULL);

        /* zonetag */
        if (!atleast(retval, codep + 1)) return -1;

        switch (zonetag) {
        case ZONE:
                retval->data[codep++].value = B_TIMEZONE;

                /* time-zone offset in minutes */
                if (!atleast(retval, codep + 1) ||
                    sscanf(zone, "%c%02u%02u", &sign, &hours, &minutes) != 3)
                    return -1;

                retval->data[codep++].value = (sign == '-' ? -1 : 1) * (hours * 60) + minutes;
                break;
        case ORIGINALZONE:
                retval->data[codep++].value = B_ORIGINALZONE;
                break;
        default:
                return -1;
        }

        return codep;
}
/* given a location and a string list, compile it into almost-flat form.
 * <list len> <string len><string ptr><string len><string ptr> etc... */
static int bc_stringlist_generate(int codep, bytecode_info_t *retval,
                                  strarray_t *sa)
{
    int len_codep = codep;
    int strcount = 0;
    int i;

    codep++;

    /* Bounds check the string list length */
    if(!atleast(retval,codep+1))
        return -1;

    if (sa) {
        for (i = 0 ; i < sa->count ; i++) {
            char *s = sa->data[i];

            strcount++;
            assert(s!=NULL);

            /* Bounds check for each string before we allocate it */
            if(!atleast(retval,codep+2))
                return -1;

            retval->data[codep++].len = strlen(s);
            retval->data[codep++].str = s;
        }
    }

    retval->data[len_codep].listlen = strcount;
    return codep;
}
/* <list len> <next test ptr> <test ...> <next test ptr> <test ...> ... */
static int bc_testlist_generate(int codep, bytecode_info_t *retval,
                                testlist_t *tl)
{
    int len_codep = codep;
    int testcount = 0;
    testlist_t *cur;

    codep++;

    /* Bounds check the test list length */
    if(!atleast(retval,codep+1))
        return -1;

    for(cur=tl; cur; cur=cur->next) {
        int oldcodep = codep;

        /* Make room for tail marker */
        if(!atleast(retval,codep+1))
            return -1;

        testcount++;
        codep = bc_test_generate(codep+1, retval, cur->t);

        retval->data[oldcodep].jump = codep;
    }

    retval->data[len_codep].listlen = testcount;

    return codep;
}
Example #4
0
/* given a location and a string list, compile it into almost-flat form.
 * <list len> <string len><string ptr><string len><string ptr> etc... */
static int bc_stringlist_generate(int codep, bytecode_info_t *retval,
				  stringlist_t *sl) 
{
    int len_codep = codep;
    int strcount = 0;
    stringlist_t *cur;
    
    codep++;

    /* Bounds check the string list length */
    if(!atleast(retval,codep+1)) 
	return -1;

    for(cur=sl; cur; cur=cur->next) 
    {
	strcount++;
	assert((cur->s)!=NULL);
	
	/* Bounds check for each string before we allocate it */
	if(!atleast(retval,codep+2)) 
	    return -1;

	retval->data[codep++].len = strlen(cur->s);
	retval->data[codep++].str = cur->s;
    }
    
    retval->data[len_codep].listlen = strcount;
    return codep;
}
/* writes a single comparator into almost-flat form starting at codep.
 * will always write out 3 words
 * returns the next code location or -1 on error. */
static int bc_comparator_generate(int codep, bytecode_info_t *retval,
                                  int comptag, int relat,
                                  const char *comparator)
{
    assert(retval != NULL);

    /* comptag */
    if (!atleast(retval, codep + 1)) return -1;

    switch (comptag) {
    case IS:
        retval->data[codep++].value = B_IS;
        break;
    case CONTAINS:
        retval->data[codep++].value = B_CONTAINS;
        break;
    case MATCHES:
        retval->data[codep++].value = B_MATCHES;
        break;
#ifdef ENABLE_REGEX
    case REGEX:
        retval->data[codep++].value = B_REGEX;
        break;
#endif
    case COUNT:
        retval->data[codep++].value = B_COUNT;
        break;
    case VALUE:
        retval->data[codep++].value = B_VALUE;
        break;

    default:
        return -1;
    }

    /*relation*/
    codep = bc_relation_generate(codep, retval, relat);

    /* comparator (value specified with :comparator) */
    if (!atleast(retval, codep + 1)) return -1;

    /* xxx perhaps extend comparator.h to have
       lookup_comp return an index, and then
       lookup_by_index return the actual comparator?

       we can then eliminate the comptag above, too. */

    if (!strcmp (comparator, "i;octet"))
        retval->data[codep++].value = B_OCTET;
    else if (!strcmp (comparator, "i;ascii-casemap"))
        retval->data[codep++].value = B_ASCIICASEMAP;
    else if (!strcmp (comparator, "i;ascii-numeric"))
        retval->data[codep++].value = B_ASCIINUMERIC;

    return codep;
}
/* output a relation into almost-flat form at codep.
 * returns new codep on success, -1 on failure. */
static int bc_relation_generate(int codep, bytecode_info_t *retval, int relat)
{
    if (!atleast(retval, codep + 1)) return -1;
    switch (relat)
    {
    case GT:
        retval->data[codep++].value= B_GT;
        break;
    case GE:
        retval->data[codep++].value= B_GE;
        break;
    case LT:
        retval->data[codep++].value= B_LT;
        break;
    case LE:
        retval->data[codep++].value= B_LE;
        break;
    case EQ:
        retval->data[codep++].value= B_EQ;
        break;
    case NE:
        retval->data[codep++].value= B_NE;
        break;
    default:
        /* comparator has no relational field */
        retval->data[codep++].value=  -1;
        break;
    }
    return codep;
}
Example #7
0
  ExecStatus
  LqView<VX,VY,VZ,shr>::propagate(Space& home, const ModEventDelta&) {
    count(home);
    GECODE_ME_CHECK(z.gq(home,atleast()));

    if (z.max() == atleast()) {
      GECODE_ES_CHECK(post_false(home,x,y));
      return home.ES_SUBSUMED(*this);
    }

    if (x.size() == 0)
      return home.ES_SUBSUMED(*this);

    if (z.assigned()) {
      VY yc(y);
      GECODE_REWRITE(*this,(LqInt<VX,VY>::post(home(*this),x,yc,z.val()+c)));
    }

    return shr ? ES_NOFIX : ES_FIX;
  }
Example #8
0
  ExecStatus
  EqView<VX,VY,VZ,shr,dom>::propagate(Space& home, const ModEventDelta&) {
    count(home);

    GECODE_ME_CHECK(z.gq(home,atleast()));
    GECODE_ME_CHECK(z.lq(home,atmost()));

    if (z.assigned()) {
      if (z.val() == atleast()) {
        GECODE_ES_CHECK(post_false(home,x,y));
        return home.ES_SUBSUMED(*this);
      }
      if (z.val() == atmost()) {
        GECODE_ES_CHECK(post_true(home,x,y));
        return home.ES_SUBSUMED(*this);
      }
      if (!dom || (vtd(y) != VTD_VARVIEW)) {
        VY yc(y);
        GECODE_REWRITE(*this,(EqInt<VX,VY>
                              ::post(home(*this),x,yc,z.val()+c)));    
      }
    }


    if (dom && (vtd(y) == VTD_VARVIEW) && (z.min() > 0)) {
      /* 
       * Only if the propagator is at fixpoint here, continue
       * when things are shared: the reason is that prune
       * requires that the views in x overlap with y!
       */
      if (shr && (VX::me(Propagator::modeventdelta()) != ME_INT_NONE))
        return ES_NOFIX;

      GECODE_ES_CHECK(prune(home,x,y));

      return ES_NOFIX;
    }
    
    return shr ? ES_NOFIX : ES_FIX;
  }
/* sieve is cool because everything is immediate! */
static int bc_action_generate(int codep, bytecode_info_t *retval,
                              commandlist_t *c)
{
    int jumploc;

    if (!retval)
        return -1;

    if (c == NULL) {
        if (!atleast(retval, codep+1)) return -1;
        retval->data[codep++].op = B_NULL;
    }
    else {
        do {
            switch(c->type) {
            case STOP:
                /* STOP (no arguments) */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_STOP;
                break;

            case DISCARD:
                /* DISCARD (no arguments) */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_DISCARD;
                break;

            case KEEP:
                /* KEEP
                   STRINGLIST flags
                   VALUE copy
                */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_KEEP;
                codep = bc_stringlist_generate(codep,retval,c->u.k.flags);
                if (codep == -1) return -1;
                if(!atleast(retval,codep+1)) return -1;
                retval->data[codep++].value = c->u.k.copy;
                break;

            case MARK:
                /* MARK (no arguments) */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_MARK;
                break;

            case UNMARK:
                /* UNMARK (no arguments) */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_UNMARK;
                break;

            case RETURN:
                /* RETURN (no arguments) */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_RETURN;
                break;

            case DENOTIFY:
                /* DENOTIFY  */
                if (!atleast(retval, codep+6)) return -1;
                retval->data[codep++].op = B_DENOTIFY;
                switch(c->u.d.priority) {
                case LOW:
                    retval->data[codep++].value = B_LOW;
                    break;
                case NORMAL:
                    retval->data[codep++].value = B_NORMAL;
                    break;
                case HIGH:
                    retval->data[codep++].value = B_HIGH;
                    break;
                case ANY:
                    retval->data[codep++].value = B_ANY;
                    break;
                default:
                    return -1;
                }
                switch(c->u.d.comptag) {
                case IS:
                    retval->data[codep++].value = B_IS;
                    break;
                case CONTAINS:
                    retval->data[codep++].value = B_CONTAINS;
                    break;
                case MATCHES:
                    retval->data[codep++].value = B_MATCHES;
                    break;
#ifdef ENABLE_REGEX
                case REGEX:
                    retval->data[codep++].value = B_REGEX;
                    break;
#endif
                case ANY:
                    retval->data[codep++].value = B_ANY;
                    break;
                default:
                    return -1;
                }
                codep = bc_relation_generate(codep, retval, c->u.d.relation);

                if(c->u.d.pattern) {
                    retval->data[codep++].len = strlen(c->u.d.pattern);
                    retval->data[codep++].str = c->u.d.pattern;
                }
                else {
                    retval->data[codep++].len = -1;
                    retval->data[codep++].str = NULL;
                }

                break;

            case REJCT:
                /* REJECT (STRING: len + dataptr) */
                if (!atleast(retval, codep+3)) return -1;
                retval->data[codep++].op = B_REJECT;
                retval->data[codep++].len = strlen(c->u.str);
                retval->data[codep++].str = c->u.str;
                break;

            case FILEINTO:
                /* FILEINTO
                   STRINGLIST flags
                   VALUE copy
                   STRING folder
                */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_FILEINTO;
                codep = bc_stringlist_generate(codep, retval, c->u.f.flags);
                if(codep == -1) return -1;
                if (!atleast(retval, codep+3)) return -1;
                retval->data[codep++].value = c->u.f.copy;
                retval->data[codep++].len = strlen(c->u.f.folder);
                retval->data[codep++].str = c->u.f.folder;
                break;

            case REDIRECT:
                /* REDIRECT
                   VALUE copy
                   STRING address
                */
                if (!atleast(retval, codep+4)) return -1;
                retval->data[codep++].op = B_REDIRECT;
                retval->data[codep++].value = c->u.r.copy;
                retval->data[codep++].len = strlen(c->u.r.address);
                retval->data[codep++].str = c->u.r.address;
                break;

            case ADDFLAG:
                /* ADDFLAG stringlist */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_ADDFLAG;
                codep = bc_stringlist_generate(codep,retval,c->u.sl);
                if (codep == -1) return -1;
                break;

            case SETFLAG:
                /* SETFLAG stringlist */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_SETFLAG;
                codep = bc_stringlist_generate(codep,retval,c->u.sl);
                if (codep == -1) return -1;
                break;

            case REMOVEFLAG:
                /* REMOVEFLAG stringlist */
                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_REMOVEFLAG;
                codep = bc_stringlist_generate(codep,retval,c->u.sl);
                if (codep == -1) return -1;
                break;

            case NOTIFY:
                /* NOTIFY
                   (STRING: len + dataptr)
                   (STRING: len + dataptr)
                   stringlist
                   (STRING: len + dataptr)
                   (STRING: len + dataptr)
                   method/id /options list/priority/message
                */

                if (!atleast(retval, codep+5)) return -1;
                retval->data[codep++].op = B_NOTIFY;

                retval->data[codep++].len = strlen(c->u.n.method);
                retval->data[codep++].str = c->u.n.method;

                if (c->u.n.id)
                {
                    retval->data[codep++].len = strlen(c->u.n.id);
                    retval->data[codep++].str = c->u.n.id;
                }
                else
                {
                    retval->data[codep++].len = -1;
                    retval->data[codep++].str = NULL;
                }

                codep = bc_stringlist_generate(codep,retval,c->u.n.options);
                if (codep == -1) return -1;

                if (!atleast(retval, codep+3)) return -1;

                switch(c->u.n.priority) {
                case LOW:
                    retval->data[codep++].value = B_LOW;
                    break;
                case NORMAL:
                    retval->data[codep++].value = B_NORMAL;
                    break;
                case HIGH:
                    retval->data[codep++].value = B_HIGH;
                    break;
                case ANY:
                    retval->data[codep++].value = B_ANY;
                    break;
                default:
                    return -1;
                }

                retval->data[codep++].len = strlen(c->u.n.message);
                retval->data[codep++].str = c->u.n.message;
                break;

            case VACATION:
                /* VACATION
                   STRINGLIST addresses
                   STRING subject (if len is -1, then subject was NULL)
                   STRING message (again, len == -1 means message was NULL)
                   VALUE seconds
                   VALUE mime
                   STRING from (if len is -1, then from was NULL)
                   STRING handle (again, len == -1 means handle was NULL)
                */

                if (!atleast(retval, codep+1)) return -1;
                retval->data[codep++].op = B_VACATION;

                codep = bc_stringlist_generate(codep,retval,c->u.v.addresses);
                if (codep == -1) return -1;

                if (!atleast(retval, codep+2)) return -1;
                if (c->u.v.subject) {
                    retval->data[codep++].len = strlen(c->u.v.subject);
                    retval->data[codep++].str = c->u.v.subject;
                }
                else {
                    retval->data[codep++].len = -1;
                    retval->data[codep++].str = NULL;
                }

                if (!atleast(retval, codep+2)) return -1;
                if (c->u.v.message) {
                    retval->data[codep++].len = strlen(c->u.v.message);
                    retval->data[codep++].str = c->u.v.message;
                }
                else {
                    retval->data[codep++].len = -1;
                    retval->data[codep++].str = NULL;
                }

                if (!atleast(retval, codep+2)) return -1;
                retval->data[codep++].value = c->u.v.seconds;
                retval->data[codep++].value = c->u.v.mime;

                if (!atleast(retval, codep+2)) return -1;
                if (c->u.v.from) {
                    retval->data[codep++].len = strlen(c->u.v.from);
                    retval->data[codep++].str = c->u.v.from;
                }
                else {
                    retval->data[codep++].len = -1;
                    retval->data[codep++].str = NULL;
                }

                if (!atleast(retval, codep+2)) return -1;
                if (c->u.v.handle) {
                    retval->data[codep++].len = strlen(c->u.v.handle);
                    retval->data[codep++].str = c->u.v.handle;
                }
                else {
                    retval->data[codep++].len = -1;
                    retval->data[codep++].str = NULL;
                }

                if (codep == -1) return -1;
                break;

            case INCLUDE:
                /* INCLUDE
                   VALUE location + (once << 6) + (optional << 7)
                   STRING filename */
                if (!atleast(retval, codep+4)) return -1;
                retval->data[codep++].op = B_INCLUDE;

                switch(c->u.inc.location) {
                case PERSONAL:
                    retval->data[codep].value = B_PERSONAL;
                    break;
                case GLOBAL:
                    retval->data[codep].value = B_GLOBAL;
                    break;
                default:
                    return -1;
                }

                retval->data[codep++].value |= (c->u.inc.once << 6)
                                            | (c->u.inc.optional << 7);
                retval->data[codep++].len = strlen(c->u.inc.script);
                retval->data[codep++].str = c->u.inc.script;
                break;

            case IF:
            {
                int jumpVal;
                /* IF
                   (int: begin then block)
                   (int: end then block/begin else block)
                   (int:end else block) (-1 if no else block)
                   (test)
                   (then block)
                   (else block)(optional)
                */

                /* Allocate operator + jump table offsets */
                if (!atleast(retval, codep+4)) return -1;

                jumploc = codep+4;
                retval->data[codep++].op = B_IF;

                /* begining of then  code */
                jumpVal = bc_test_generate(jumploc,retval,c->u.i.t);
                if (jumpVal == -1)
                    return -1;
                else {
                    retval->data[codep].jump = jumpVal;
                    codep++;
                }

                /* find then code and offset to else code,
                 * we want to write this code starting at the offset we
                 * just found */

                jumpVal = bc_action_generate(jumpVal,retval, c->u.i.do_then);
                if (jumpVal == -1)
                    return -1;
                else
                    retval->data[codep].jump = jumpVal;

                codep++;
                /* write else code if its there*/
                if (c->u.i.do_else) {
                    jumpVal = bc_action_generate(jumpVal,retval, c->u.i.do_else);
                    if(jumpVal == -1)
                        return -1;
                    else
                        retval->data[codep].jump = jumpVal;

                    /* Update code pointer to end of else code */
                    codep = retval->data[codep].jump;
                } else {
                    /*there is no else block, so its -1*/
                    retval->data[codep].jump = -1;
                    /* Update code pointer to end of then code */
                    codep = retval->data[codep-1].jump;
                }

            }
                break;

            default:
                /* no such action known */
                return -1;
            }

            /* generate from next command */
            c = c->next;
        } while(c);
    }

    /* scriptend may be updated before the end, but it will be
     * updated at the end, which is what matters. */
    retval->scriptend = codep;

    return codep;
}
Example #10
0
/* writes a single test into almost-flat form starting at codep.
 * returns the next code location or -1 on error. */
static int bc_test_generate(int codep, bytecode_info_t *retval, test_t *t)
{
    if(!retval) return -1;
    switch(t->type) {
    case STRUE: /* BC_TRUE */
        if(!atleast(retval,codep+1)) return -1;
        retval->data[codep++].op = BC_TRUE;
        break;
    case SFALSE:/* BC_FALSE */
        if(!atleast(retval,codep+1)) return -1;
        retval->data[codep++].op = BC_FALSE;
        break;
    case NOT: /* BC_NOT {subtest : test} */
        if(!atleast(retval,codep+1)) return -1;
        retval->data[codep++].op = BC_NOT;
        codep = bc_test_generate(codep, retval, t->u.t);
        if (codep == -1) return -1;
        break;
    case SIZE: /* BC_SIZE (B_OVER | B_UNDER) {size : int} */
        if(!atleast(retval,codep+3)) return -1;
        retval->data[codep++].op = BC_SIZE;
        retval->data[codep++].value = (t->u.sz.t == OVER
                                       ? B_OVER : B_UNDER);
        retval->data[codep++].value = t->u.sz.n;
        break;
    case EXISTS:/* BC_EXISTS { headers : string list } */
        if(!atleast(retval,codep+1)) return -1;
        retval->data[codep++].op = BC_EXISTS;
        codep= bc_stringlist_generate(codep, retval, t->u.sl);
        break;
    case ANYOF:/* BC_ANYOF { tests : test list } */
        if(!atleast(retval,codep+1)) return -1;
        retval->data[codep++].op = BC_ANYOF;
        codep=bc_testlist_generate(codep, retval, t->u.tl);
        if (codep == -1) return -1;
        break;
    case ALLOF: /* BC_ALLOF { tests : test list } */
        if(!atleast(retval,codep+1)) return -1;
        retval->data[codep++].op = BC_ALLOF;
        codep= bc_testlist_generate(codep, retval, t->u.tl);
        if (codep == -1) return -1;
        break;
    case HEADER:
    case HASFLAG:
        /* BC_HEADER { i: index } { c: comparator }
         * { haystacks : string list } { patterns : string list }
         *
         * BC_HASFLAG { c: comparator }
         * { haystacks : string list } { patterns : string list }
         */

        if(!atleast(retval,codep + 1)) return -1;
        retval->data[codep++].op = (t->type == HEADER)
            ? BC_HEADER : BC_HASFLAG;

        if (t->type == HEADER) {
        /* index */
        if(!atleast(retval,codep + 1)) return -1;
        retval->data[codep++].value = t->u.h.index;
        }

        /* comparator */
        codep = bc_comparator_generate(codep, retval,
                                       t->u.h.comptag,
                                       t->u.h.relation,
                                       t->u.h.comparator);
        if (codep == -1) return -1;

        /* haystacks */
        codep = bc_stringlist_generate(codep, retval, t->u.h.sl);
        if (codep == -1) return -1;

        /* pattern */
        codep = bc_stringlist_generate(codep, retval, t->u.h.pl);
        if (codep == -1) return -1;
        break;
    case ADDRESS:
    case ENVELOPE:
        /* BC_ADDRESS {i : index } {c : comparator}
           (B_ALL | B_LOCALPART | ...) { header : string list }
           { pattern : string list }

           BC_ENVELOPE {c : comparator}
           (B_ALL | B_LOCALPART | ...) { header : string list }
           { pattern : string list } */

        if(!atleast(retval,codep+1)) return -1;

        retval->data[codep++].op = (t->type == ADDRESS)
            ? BC_ADDRESS : BC_ENVELOPE;

        /* index */
        if (t->type == ADDRESS) {
                if(!atleast(retval,codep+1)) return -1;
                retval->data[codep++].value = t->u.ae.index;
        }

        codep = bc_comparator_generate(codep, retval,t->u.ae.comptag,
                                       t->u.ae.relation,
                                       t->u.ae.comparator);
        if (codep == -1) return -1;

        if(!atleast(retval,codep+1)) return -1;

        /*address part*/
        switch(t->u.ae.addrpart) {
        case ALL:
            retval->data[codep++].value = B_ALL;
            break;
        case LOCALPART:
            retval->data[codep++].value = B_LOCALPART;
            break;
        case DOMAIN:
            retval->data[codep++].value = B_DOMAIN;
            break;
        case USER:
            retval->data[codep++].value = B_USER;
            break;
        case DETAIL:
            retval->data[codep++].value = B_DETAIL;
            break;
        default:
            return -1;
        }

        /*headers*/
        codep = bc_stringlist_generate(codep, retval, t->u.ae.sl);
        if (codep == -1) return -1;

        /*patterns*/
        codep = bc_stringlist_generate(codep, retval, t->u.ae.pl);
        if (codep == -1) return -1;

        break;
    case BODY:
        /* BC_BODY {c : comparator} (B_RAW | B_TEXT | ...)
           { content-types : stringlist }
           { offset : int }
           { pattern : string list } */

        if(!atleast(retval,codep+1)) return -1;

        retval->data[codep++].op = BC_BODY;

        codep = bc_comparator_generate(codep, retval,t->u.b.comptag,
                                       t->u.b.relation,
                                       t->u.b.comparator);
        if (codep == -1) return -1;

        if(!atleast(retval,codep+2)) return -1;

        /*transform*/
        switch(t->u.b.transform) {
        case RAW:
            retval->data[codep++].value = B_RAW;
            break;
        case TEXT:
            retval->data[codep++].value = B_TEXT;
            break;
        case CONTENT:
            retval->data[codep++].value = B_CONTENT;
            break;
        default:
            return -1;
        }

        /*offset*/
        retval->data[codep++].value = t->u.b.offset;

        /*content-types*/
        codep = bc_stringlist_generate(codep, retval, t->u.b.content_types);
        if (codep == -1) return -1;

        /*patterns*/
        codep = bc_stringlist_generate(codep, retval, t->u.b.pl);
        if (codep == -1) return -1;

        break;
    case DATE:
    case CURRENTDATE:
        /* BC_DATE { i: index } { time-zone: string} { c: comparator }
         *         { header-name : string } { date-part: string }
         *         { key-list : string list }
         *
         * BC_CURRENTDATE { time-zone: string} { c: comparator }
         *         { date-part: string } { key-list : string list }
        */

        if(!atleast(retval,codep + 1)) return -1;
        retval->data[codep++].op = (DATE == t->type) ? BC_DATE : BC_CURRENTDATE;

        /* index */
        if (DATE == t->type) {
                if(!atleast(retval,codep + 1)) return -1;
                retval->data[codep++].value = t->u.dt.index;
        }

        /* zone */
        codep = bc_zone_generate(codep, retval,
                                 t->u.dt.zonetag,
                                 t->u.dt.zone);
        if (codep == -1) return -1;

        /* comparator */
        codep = bc_comparator_generate(codep, retval,
                                       t->u.dt.comptag,
                                       t->u.dt.relation,
                                       t->u.dt.comparator);
        if (codep == -1) return -1;

        /* date-part */
        if(!atleast(retval,codep + 1)) return -1;
        switch (t->u.dt.date_part) {
        case YEAR:
                retval->data[codep++].value = B_YEAR;
                break;
        case MONTH:
                retval->data[codep++].value = B_MONTH;
                break;
        case DAY:
                retval->data[codep++].value = B_DAY;
                break;
        case DATE:
                retval->data[codep++].value = B_DATE;
                break;
        case JULIAN:
                retval->data[codep++].value = B_JULIAN;
                break;
        case HOUR:
                retval->data[codep++].value = B_HOUR;
                break;
        case MINUTE:
                retval->data[codep++].value = B_MINUTE;
                break;
        case SECOND:
                retval->data[codep++].value = B_SECOND;
                break;
        case TIME:
                retval->data[codep++].value = B_TIME;
                break;
        case ISO8601:
                retval->data[codep++].value = B_ISO8601;
                break;
        case STD11:
                retval->data[codep++].value = B_STD11;
                break;
        case ZONE:
                retval->data[codep++].value = B_ZONE;
                break;
        case WEEKDAY:
                retval->data[codep++].value = B_WEEKDAY;
                break;
        }

        if (DATE == t->type) {
                /* header-name */
                if(!atleast(retval,codep + 2)) return -1;
                retval->data[codep++].len = strlen(t->u.dt.header_name);
                retval->data[codep++].str = t->u.dt.header_name;
        }

        /* keywords */
        codep = bc_stringlist_generate(codep, retval, t->u.dt.kl);
        if (codep == -1) return -1;

        break;
    default:
        return -1;

    }
    return codep;
}
Example #11
0
/* writes a single test into almost-flat form starting at codep.
 * returns the next code location or -1 on error. */
static int bc_test_generate(int codep, bytecode_info_t *retval, test_t *t)
{
    if(!retval) return -1;
    switch(t->type) {
    case STRUE: /* BC_TRUE */
	if(!atleast(retval,codep+1)) return -1;
	retval->data[codep++].op = BC_TRUE;
	break;
    case SFALSE:/* BC_FALSE */
	if(!atleast(retval,codep+1)) return -1;
	retval->data[codep++].op = BC_FALSE;
	break;
    case NOT: /* BC_NOT {subtest : test} */
	if(!atleast(retval,codep+1)) return -1;
	retval->data[codep++].op = BC_NOT;
	codep = bc_test_generate(codep, retval, t->u.t);
	if (codep == -1) return -1;
	break;
    case SIZE: /* BC_SIZE (B_OVER | B_UNDER) {size : int} */
	if(!atleast(retval,codep+3)) return -1;
	retval->data[codep++].op = BC_SIZE;
	retval->data[codep++].value = (t->u.sz.t == OVER
				       ? B_OVER : B_UNDER);
	retval->data[codep++].value = t->u.sz.n;
	break;
    case EXISTS:/* BC_EXISTS { headers : string list } */
	if(!atleast(retval,codep+1)) return -1;
	retval->data[codep++].op = BC_EXISTS;
	codep= bc_stringlist_generate(codep, retval, t->u.sl);
	break;
    case ANYOF:/* BC_ANYOF { tests : test list } */
	if(!atleast(retval,codep+1)) return -1;
	retval->data[codep++].op = BC_ANYOF;
	codep=bc_testlist_generate(codep, retval, t->u.tl);
	if (codep == -1) return -1;
	break;
    case ALLOF: /* BC_ALLOF { tests : test list } */
	if(!atleast(retval,codep+1)) return -1;
	retval->data[codep++].op = BC_ALLOF;
	codep= bc_testlist_generate(codep, retval, t->u.tl);
	if (codep == -1) return -1;
	break;
    case HEADER:
	/* BC_HEADER { c: comparator } { headers : string list }
	   { patterns : string list } 
	*/
      
	if(!atleast(retval,codep + 1)) return -1;
	retval->data[codep++].op = BC_HEADER;
      
	/* comparator */
	codep = bc_comparator_generate(codep, retval,
				       t->u.h.comptag,
				       t->u.h.relation,
				       t->u.h.comparator);
	if (codep == -1) return -1;
      
	/* headers */
	codep = bc_stringlist_generate(codep, retval, t->u.h.sl);
	if (codep == -1) return -1;
      
	/* pattern */
	codep = bc_stringlist_generate(codep, retval, t->u.h.pl);
	if (codep == -1) return -1;
	break;
    case ADDRESS:
    case ENVELOPE:
	/* (BC_ADDRESS | BC_ENVELOPE) {c : comparator} 
	   (B_ALL | B_LOCALPART | ...) { header : string list }
	   { pattern : string list } */
      
	if(!atleast(retval,codep+1)) return -1;
      
	retval->data[codep++].op = (t->type == ADDRESS)
	    ? BC_ADDRESS : BC_ENVELOPE;
            
	codep = bc_comparator_generate(codep, retval,t->u.ae.comptag,
				       t->u.ae.relation, 
				       t->u.ae.comparator);
	if (codep == -1) return -1;

	if(!atleast(retval,codep+1)) return -1;

	/*address part*/
	switch(t->u.ae.addrpart) {
	case ALL:
	    retval->data[codep++].value = B_ALL;
	    break;
	case LOCALPART:
	    retval->data[codep++].value = B_LOCALPART;
	    break;
	case DOMAIN:
	    retval->data[codep++].value = B_DOMAIN;
	    break;
	case USER:
	    retval->data[codep++].value = B_USER;
	    break;
	case DETAIL:
	    retval->data[codep++].value = B_DETAIL;
	    break;
	default:
	    return -1;
	}

	/*headers*/
	codep = bc_stringlist_generate(codep, retval, t->u.ae.sl);
	if (codep == -1) return -1;

	/*patterns*/
	codep = bc_stringlist_generate(codep, retval, t->u.ae.pl);
	if (codep == -1) return -1;
     
	break;
    case BODY:
	/* BC_BODY {c : comparator} (B_RAW | B_TEXT | ...)
	   { content-types : stringlist }
	   { offset : int }
	   { pattern : string list } */
      
	if(!atleast(retval,codep+1)) return -1;
      
	retval->data[codep++].op = BC_BODY;
            
	codep = bc_comparator_generate(codep, retval,t->u.b.comptag,
				       t->u.b.relation, 
				       t->u.b.comparator);
	if (codep == -1) return -1;

	if(!atleast(retval,codep+2)) return -1;

	/*transform*/
	switch(t->u.b.transform) {
	case RAW:
	    retval->data[codep++].value = B_RAW;
	    break;
	case TEXT:
	    retval->data[codep++].value = B_TEXT;
	    break;
	case CONTENT:
	    retval->data[codep++].value = B_CONTENT;
	    break;
	default:
	    return -1;
	}

	/*offset*/
	retval->data[codep++].value = t->u.b.offset;

	/*content-types*/
	codep = bc_stringlist_generate(codep, retval, t->u.b.content_types);
	if (codep == -1) return -1;

	/*patterns*/
	codep = bc_stringlist_generate(codep, retval, t->u.b.pl);
	if (codep == -1) return -1;
     
	break;
    default:
	return -1;
      
    }
    return codep;
}