40 |
static void rc_asgn_destroy(RC_ASGN *asgn); |
static void rc_asgn_destroy(RC_ASGN *asgn); |
41 |
|
|
42 |
static void rc_bool_destroy(RC_BOOL *bool); |
static void rc_bool_destroy(RC_BOOL *bool); |
43 |
|
|
44 |
|
static void rc_level_print(int level, char *str); |
45 |
|
|
46 |
static RC_NODE *rc_node_create(enum rc_node_type t); |
static RC_NODE *rc_node_create(enum rc_node_type t); |
47 |
static void rc_node_destroy(RC_NODE *node); |
static void rc_node_destroy(RC_NODE *node); |
73 |
RC_NODE *node; |
RC_NODE *node; |
74 |
RC_REGEX *regex; |
RC_REGEX *regex; |
75 |
int num; |
int num; |
76 |
|
struct { |
77 |
|
int part; |
78 |
|
char *key; |
79 |
|
} msgpart; |
80 |
}; |
}; |
81 |
|
|
82 |
%token EOL T_BEGIN T_END AND OR EQ NE |
%token EOL T_BEGIN T_END AND OR |
83 |
%token T_HEADER T_COMMAND T_BODY IF FI ELSE RULE DONE |
%token T_HEADER T_COMMAND T_BODY IF FI ELSE RULE DONE |
84 |
|
%token CALL STOP ADD REMOVE MODIFY |
85 |
%token <string> IDENT STRING REGEX D_BEGIN |
%token <string> IDENT STRING REGEX D_BEGIN |
86 |
|
%token <num> T_MSGPART |
87 |
|
|
88 |
%left OR |
%left OR |
89 |
%left AND |
%left AND |
90 |
%left NOT |
%left NOT |
91 |
|
|
92 |
%type <string> begin keyword string option |
%type <string> begin keyword string option opt_key |
93 |
%type <section> section seclist |
%type <section> section seclist |
94 |
%type <stmtlist> stmtlist |
%type <stmtlist> stmtlist |
95 |
%type <stmt> stmt asgn_stmt cond_stmt rule_stmt |
%type <stmt> stmt asgn_stmt cond_stmt rule_stmt inst_stmt |
96 |
%type <num> part optlist |
%type <num> optlist |
97 |
%type <node> rule_start cond expr |
%type <node> rule_start cond expr |
98 |
|
%type <msgpart> msgpart |
99 |
|
|
100 |
%% |
%% |
101 |
|
|
167 |
| asgn_stmt EOL |
| asgn_stmt EOL |
168 |
| cond_stmt EOL |
| cond_stmt EOL |
169 |
| rule_stmt EOL |
| rule_stmt EOL |
170 |
|
| inst_stmt EOL |
171 |
; |
; |
172 |
|
|
173 |
asgn_stmt: keyword EQ { verbatim(); } STRING |
asgn_stmt: keyword '=' { verbatim(); } STRING |
174 |
{ |
{ |
175 |
$$ = rc_stmt_create(rc_stmt_asgn); |
$$ = rc_stmt_create(rc_stmt_asgn); |
176 |
$$->v.asgn.lhs = $1; |
$$->v.asgn.lhs = $1; |
177 |
$$->v.asgn.rhs = $4; |
$$->v.asgn.rhs = $4; |
178 |
} |
} |
179 |
| keyword REGEX /* Compatibility syntax */ |
; |
|
{ |
|
|
$$ = rc_stmt_create(rc_stmt_asgn); |
|
|
$$->v.asgn.lhs = $1; |
|
|
$$->v.asgn.rhs = $2; |
|
|
} |
|
|
; |
|
180 |
|
|
181 |
keyword : IDENT |
keyword : IDENT |
182 |
; |
; |
225 |
} |
} |
226 |
; |
; |
227 |
|
|
228 |
expr : part '[' string ']' optlist string |
meq : /* empty */ |
229 |
{ |
| '=' |
230 |
$$ = rc_node_create(rc_node_expr); |
; |
231 |
$$->v.expr.part = $1; |
|
232 |
$$->v.expr.key = $3; |
opt_key : /* empty */ |
|
$$->v.expr.re = anubis_regex_compile($6, $5); |
|
|
} |
|
|
| part optlist string |
|
233 |
{ |
{ |
234 |
$$ = rc_node_create(rc_node_expr); |
$$ = NULL; |
|
$$->v.expr.part = $1; |
|
|
$$->v.expr.key = NULL; |
|
|
$$->v.expr.re = anubis_regex_compile($3, $2); |
|
235 |
} |
} |
236 |
| T_BODY optlist string |
| '[' string ']' |
237 |
{ |
{ |
238 |
$$ = rc_node_create(rc_node_expr); |
$$ = $2; |
|
$$->v.expr.part = BODY; |
|
|
$$->v.expr.key = NULL; |
|
|
$$->v.expr.re = anubis_regex_compile($3, $2); |
|
239 |
} |
} |
240 |
; |
; |
241 |
|
|
242 |
part : T_HEADER |
msgpart : T_MSGPART opt_key |
243 |
|
{ |
244 |
|
$$.part = $1; |
245 |
|
$$.key = $2; |
246 |
|
} |
247 |
|
| '[' string ']' |
248 |
{ |
{ |
249 |
$$ = HEADER; |
$$.part = HEADER; |
250 |
|
$$.key = $2; |
251 |
} |
} |
252 |
| T_COMMAND |
; |
253 |
|
|
254 |
|
expr : msgpart meq optlist string |
255 |
{ |
{ |
256 |
$$ = COMMAND; |
$$ = rc_node_create(rc_node_expr); |
257 |
|
$$->v.expr.part = $1.part; |
258 |
|
$$->v.expr.key = $1.key; |
259 |
|
$$->v.expr.re = anubis_regex_compile($4, $3); |
260 |
} |
} |
261 |
; |
; |
262 |
|
|
319 |
| IDENT |
| IDENT |
320 |
; |
; |
321 |
|
|
322 |
|
inst_stmt: ADD msgpart string |
323 |
|
{ |
324 |
|
$$ = rc_stmt_create(rc_stmt_inst); |
325 |
|
$$->v.inst.opcode = inst_add; |
326 |
|
$$->v.inst.part = $2.part; |
327 |
|
$$->v.inst.key = $2.key; |
328 |
|
$$->v.inst.key2 = NULL; |
329 |
|
$$->v.inst.arg = $3; |
330 |
|
} |
331 |
|
| REMOVE msgpart |
332 |
|
{ |
333 |
|
$$ = rc_stmt_create(rc_stmt_inst); |
334 |
|
$$->v.inst.opcode = inst_remove; |
335 |
|
$$->v.inst.part = $2.part; |
336 |
|
$$->v.inst.key = $2.key; |
337 |
|
$$->v.inst.key2 = NULL; |
338 |
|
$$->v.inst.arg = NULL; |
339 |
|
} |
340 |
|
| MODIFY msgpart opt_key string |
341 |
|
{ |
342 |
|
$$ = rc_stmt_create(rc_stmt_inst); |
343 |
|
$$->v.inst.opcode = inst_modify; |
344 |
|
$$->v.inst.part = $2.part; |
345 |
|
$$->v.inst.key = $2.key; |
346 |
|
$$->v.inst.key2 = $3; |
347 |
|
$$->v.inst.arg = $4; |
348 |
|
} |
349 |
|
; |
350 |
|
|
351 |
%% |
%% |
352 |
|
|
353 |
int |
int |
566 |
rc_stmt_list_destroy(cond->iffalse); |
rc_stmt_list_destroy(cond->iffalse); |
567 |
} |
} |
568 |
|
|
569 |
|
/* Instructions */ |
570 |
|
|
571 |
|
void |
572 |
|
rc_inst_destroy(RC_INST *inst) |
573 |
|
{ |
574 |
|
free(inst->key); |
575 |
|
free(inst->key2); |
576 |
|
free(inst->arg); |
577 |
|
} |
578 |
|
|
579 |
|
static char * |
580 |
|
inst_name(enum rc_inst_opcode opcode) |
581 |
|
{ |
582 |
|
switch (opcode) { |
583 |
|
case inst_add: |
584 |
|
return "ADD"; |
585 |
|
case inst_remove: |
586 |
|
return "REMOVE"; |
587 |
|
case inst_modify: |
588 |
|
return "MODIFY"; |
589 |
|
} |
590 |
|
return "UNKNOWN"; |
591 |
|
} |
592 |
|
|
593 |
|
void |
594 |
|
rc_inst_print(RC_INST *inst, int level) |
595 |
|
{ |
596 |
|
rc_level_print(level, inst_name(inst->opcode)); |
597 |
|
printf(" %s[%s]", part_string(inst->part), |
598 |
|
inst->key ? inst->key : ""); |
599 |
|
if (inst->key2) |
600 |
|
printf(" [%s]", inst->key2); |
601 |
|
if (inst->arg) |
602 |
|
printf(" \"%s\"", inst->arg); |
603 |
|
} |
604 |
|
|
605 |
/* Statements */ |
/* Statements */ |
606 |
RC_STMT * |
RC_STMT * |
607 |
rc_stmt_create(enum rc_stmt_type type) |
rc_stmt_create(enum rc_stmt_type type) |
626 |
|
|
627 |
case rc_stmt_cond: |
case rc_stmt_cond: |
628 |
rc_cond_destroy(&stmt->v.cond); |
rc_cond_destroy(&stmt->v.cond); |
629 |
|
break; |
630 |
|
|
631 |
|
case rc_stmt_inst: |
632 |
|
rc_inst_destroy(&stmt->v.inst); |
633 |
} |
} |
634 |
xfree(stmt); |
xfree(stmt); |
635 |
} |
} |
686 |
rc_stmt_print(stmt->v.rule.stmt, level+1); |
rc_stmt_print(stmt->v.rule.stmt, level+1); |
687 |
rc_level_print(level, "END RULE"); |
rc_level_print(level, "END RULE"); |
688 |
break; |
break; |
689 |
|
|
690 |
|
case rc_stmt_inst: |
691 |
|
rc_inst_print(&stmt->v.inst, level); |
692 |
|
break; |
693 |
|
|
694 |
default: |
default: |
695 |
abort(); |
abort(); |
773 |
static void cond_eval(struct eval_env *env, RC_COND *cond); |
static void cond_eval(struct eval_env *env, RC_COND *cond); |
774 |
static void rule_eval(struct eval_env *env, RC_RULE *rule); |
static void rule_eval(struct eval_env *env, RC_RULE *rule); |
775 |
static void stmt_list_eval(struct eval_env *env, RC_STMT *stmt); |
static void stmt_list_eval(struct eval_env *env, RC_STMT *stmt); |
776 |
|
static void inst_eval(struct eval_env *env, RC_INST *inst); |
777 |
|
|
778 |
|
void |
779 |
|
inst_eval(struct eval_env *env, RC_INST *inst) |
780 |
|
{ |
781 |
|
char *arg, *argp = NULL; |
782 |
|
|
783 |
|
if (!env->msg) |
784 |
|
return; /* FIXME: bail out? */ |
785 |
|
|
786 |
|
if (inst->arg) { |
787 |
|
if (env->refstr) |
788 |
|
arg = argp = substitute(inst->arg, env->refstr); |
789 |
|
else |
790 |
|
arg = inst->arg; |
791 |
|
} |
792 |
|
|
793 |
|
switch (inst->opcode) { |
794 |
|
case inst_add: |
795 |
|
if (inst->part == BODY) |
796 |
|
message_add_body(env->msg, inst->key, arg); |
797 |
|
else |
798 |
|
message_add_header(env->msg, inst->key, arg); |
799 |
|
break; |
800 |
|
|
801 |
|
case inst_modify: |
802 |
|
message_modify_headers(env->msg, inst->key, inst->key2, arg); |
803 |
|
break; |
804 |
|
|
805 |
|
case inst_remove: |
806 |
|
message_remove_headers(env->msg, inst->key); |
807 |
|
break; |
808 |
|
|
809 |
|
default: |
810 |
|
abort(); |
811 |
|
} |
812 |
|
|
813 |
|
if (argp) |
814 |
|
free(argp); |
815 |
|
} |
816 |
|
|
817 |
void |
void |
818 |
asgn_eval(struct eval_env *env, RC_ASGN *asgn) |
asgn_eval(struct eval_env *env, RC_ASGN *asgn) |
819 |
{ |
{ |
956 |
|
|
957 |
case rc_stmt_rule: |
case rc_stmt_rule: |
958 |
rule_eval(env, &stmt->v.rule); |
rule_eval(env, &stmt->v.rule); |
959 |
|
break; |
960 |
|
|
961 |
|
case rc_stmt_inst: |
962 |
|
inst_eval(env, &stmt->v.inst); |
963 |
} |
} |
964 |
} |
} |
965 |
|
|