/* emit the bytecode for a test. returns -1 on failure or size of * emitted bytecode on success */ static int bc_test_emit(int fd, int *codep, bytecode_info_t *bc) { int opcode; int wrote=0;/* Relative offset to account for interleaved strings */ int ret; /* Temporary Return Value Variable */ /* Output this opcode */ opcode = bc->data[(*codep)++].op; if(write_int(fd, opcode) == -1) return -1; wrote += sizeof(int); switch(opcode) { case BC_TRUE: case BC_FALSE: /* No parameter opcodes */ break; case BC_NOT: { /* Single parameter: another test */ ret = bc_test_emit(fd, codep, bc); if(ret < 0) return -1; else wrote+=ret; break; } case BC_ALLOF: case BC_ANYOF: /*where we jump to?*/ /* Just drop a testlist */ ret = bc_testlist_emit(fd, codep, bc); if(ret < 0) return -1; else wrote+=ret; break; case BC_SIZE: /* Drop tag and number */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; if(write_int(fd, bc->data[(*codep)+1].value) == -1) return -1; wrote += 2 * sizeof(int); (*codep) += 2; break; case BC_EXISTS: { int ret; ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote += ret; break; } case BC_HEADER: case BC_HASFLAG: { int ret; if (BC_HEADER == opcode) { /* drop index */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; } /* Drop match type */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop relation*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*drop comparator */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* Now drop haystacks */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; /* Now drop needles */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; break; } case BC_ADDRESS: /* drop index */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* fall-through */ case BC_ENVELOPE: { int ret; /* Drop match type */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*drop comparator */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop relation*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop address part*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* Now drop headers */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; /* Now drop data */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; break; } case BC_BODY: { int ret; /* Drop match type */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*drop comparator */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop relation*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop transform*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop offset*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop content-types*/ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; /* Now drop data */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; break; } case BC_DATE: case BC_CURRENTDATE: { int ret; int datalen; int tmp; /* drop index */ if(BC_DATE == opcode) { if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; } /* drop zone tag */ tmp = bc->data[(*codep)].value; if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* drop timezone offset */ if (tmp == B_TIMEZONE) { if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; } /* drop match type */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* drop relation */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* drop comparator */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* drop date-part */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; if (BC_DATE == opcode) { /* drop header-name */ datalen = bc->data[(*codep)++].len; if(write_int(fd, datalen) == -1) return -1; wrote += sizeof(int); if(write(fd, bc->data[(*codep)++].str, datalen) == -1) return -1; wrote += datalen; ret = align_string(fd,datalen); if(ret == -1) return -1; wrote+=ret; } /* drop keywords */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; break; } default: /* Unknown testcode? */ return -1; } return wrote; }
/* emit the bytecode for a test. returns -1 on failure or size of * emitted bytecode on success */ static int bc_test_emit(int fd, int *codep, bytecode_info_t *bc) { int wrote=0;/* Relative offset to account for interleaved strings */ int ret; /* Temporary Return Value Variable */ /* Output this opcode */ if(write_int(fd, bc->data[(*codep)].op) == -1) return -1; wrote += sizeof(int); switch(bc->data[(*codep)++].op) { case BC_TRUE: case BC_FALSE: /* No parameter opcodes */ break; case BC_NOT: { /* Single parameter: another test */ ret = bc_test_emit(fd, codep, bc); if(ret < 0) return -1; else wrote+=ret; break; } case BC_ALLOF: case BC_ANYOF: /*where we jump to?*/ /* Just drop a testlist */ ret = bc_testlist_emit(fd, codep, bc); if(ret < 0) return -1; else wrote+=ret; break; case BC_SIZE: /* Drop tag and number */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; if(write_int(fd, bc->data[(*codep)+1].value) == -1) return -1; wrote += 2 * sizeof(int); (*codep) += 2; break; case BC_EXISTS: { int ret; ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote += ret; break; } case BC_HEADER: { int ret; /* Drop match type */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*drop comparator */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop relation*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* Now drop headers */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; /* Now drop data */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; break; } case BC_ADDRESS: case BC_ENVELOPE: { int ret; /* Drop match type */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*drop comparator */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop relation*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop address part*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /* Now drop headers */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; /* Now drop data */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; break; } case BC_BODY: { int ret; /* Drop match type */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*drop comparator */ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop relation*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop transform*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop offset*/ if(write_int(fd, bc->data[(*codep)].value) == -1) return -1; wrote += sizeof(int); (*codep)++; /*now drop content-types*/ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; /* Now drop data */ ret = bc_stringlist_emit(fd, codep, bc); if(ret < 0) return -1; wrote+=ret; break; } default: /* Unknown testcode? */ return -1; } return wrote; }