/* 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; }
/* 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; }