Case arg { 1: printf "one"; } works. You can not use two commands
after one label, yet.
This commit is contained in:
parent
4caa2231fc
commit
7db7b7db60
2 changed files with 79 additions and 8 deletions
|
@ -21,7 +21,7 @@ CF_DECLS
|
||||||
CF_KEYWORDS(FUNCTION, PRINT, CONST,
|
CF_KEYWORDS(FUNCTION, PRINT, CONST,
|
||||||
ACCEPT, REJECT, ERROR, QUITBIRD,
|
ACCEPT, REJECT, ERROR, QUITBIRD,
|
||||||
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
||||||
IF, THEN, ELSE,
|
IF, THEN, ELSE, CASE,
|
||||||
TRUE, FALSE,
|
TRUE, FALSE,
|
||||||
RTA, FROM, GW, NET,
|
RTA, FROM, GW, NET,
|
||||||
LEN,
|
LEN,
|
||||||
|
@ -29,7 +29,7 @@ CF_KEYWORDS(FUNCTION, PRINT, CONST,
|
||||||
FILTER
|
FILTER
|
||||||
)
|
)
|
||||||
|
|
||||||
%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list
|
%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list switch_body
|
||||||
%type <f> filter filter_body
|
%type <f> filter filter_body
|
||||||
%type <i> type break_command
|
%type <i> type break_command
|
||||||
%type <e> set_item set_items
|
%type <e> set_item set_items
|
||||||
|
@ -118,6 +118,8 @@ function_def:
|
||||||
cmds: /* EMPTY */ { $$ = NULL; }
|
cmds: /* EMPTY */ { $$ = NULL; }
|
||||||
| cmd cmds {
|
| cmd cmds {
|
||||||
if ($1) {
|
if ($1) {
|
||||||
|
if ($1->next)
|
||||||
|
bug("Command has next already set\n");
|
||||||
$1->next = $2;
|
$1->next = $2;
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
} else $$ = $2;
|
} else $$ = $2;
|
||||||
|
@ -160,7 +162,6 @@ constant:
|
||||||
|
|
||||||
term:
|
term:
|
||||||
term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
|
term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
|
|
||||||
| term '=' term { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '=' term { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
| term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; }
|
| term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; }
|
||||||
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
|
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
|
||||||
|
@ -231,6 +232,22 @@ var_list: /* EMPTY */ { $$ = NULL; }
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
switch_body: /* EMPTY */ { $$ = NULL; }
|
||||||
|
| term ':' block switch_body {
|
||||||
|
$$ = f_new_inst();
|
||||||
|
$$->code = 'of';
|
||||||
|
$$->a1.p = $1;
|
||||||
|
$$->a2.p = $3;
|
||||||
|
$$->next = $4;
|
||||||
|
}
|
||||||
|
| ELSE ':' block {
|
||||||
|
$$ = f_new_inst();
|
||||||
|
$$->code = 'el';
|
||||||
|
$$->a1.p = NULL;
|
||||||
|
$$->a2.p = $3;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
cmd:
|
cmd:
|
||||||
ifthen {
|
ifthen {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
@ -272,6 +289,12 @@ cmd:
|
||||||
inst = inst->next;
|
inst = inst->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
| CASE term '{' switch_body '}' {
|
||||||
|
$$ = f_new_inst();
|
||||||
|
$$->code = 'sw';
|
||||||
|
$$->a1.p = $2;
|
||||||
|
$$->a2.p = $4;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
CF_END
|
CF_END
|
||||||
|
|
|
@ -53,6 +53,8 @@ struct f_inst *startup_func = NULL;
|
||||||
int
|
int
|
||||||
val_compare(struct f_val v1, struct f_val v2)
|
val_compare(struct f_val v1, struct f_val v2)
|
||||||
{
|
{
|
||||||
|
if (v1.type != v2.type)
|
||||||
|
return CMP_ERROR;
|
||||||
switch (v1.type) {
|
switch (v1.type) {
|
||||||
case T_INT:
|
case T_INT:
|
||||||
if (v1.val.i == v2.val.i) return 0;
|
if (v1.val.i == v2.val.i) return 0;
|
||||||
|
@ -64,6 +66,14 @@ val_compare(struct f_val v1, struct f_val v2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
val_in_range(struct f_val v1, struct f_val v2)
|
||||||
|
{
|
||||||
|
if (((v1.type == T_INT) || (v1.type == T_IP)) && (v2.type == T_SET))
|
||||||
|
return !! find_tree(v2.val.t, v1);
|
||||||
|
return CMP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tree_print(struct f_tree *t)
|
tree_print(struct f_tree *t)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +108,42 @@ val_print(struct f_val v)
|
||||||
|
|
||||||
static struct rte **f_rte;
|
static struct rte **f_rte;
|
||||||
|
|
||||||
|
static struct f_val interpret(struct f_inst *what);
|
||||||
|
|
||||||
|
static struct f_val
|
||||||
|
interpret_switch(struct f_inst *what, struct f_val control)
|
||||||
|
{
|
||||||
|
struct f_val this, res;
|
||||||
|
int i;
|
||||||
|
res.type = T_VOID;
|
||||||
|
|
||||||
|
if (!what)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
switch(what->code) {
|
||||||
|
case 'el':
|
||||||
|
return interpret(what->a2.p);
|
||||||
|
|
||||||
|
case 'of':
|
||||||
|
this = interpret(what->a1.p);
|
||||||
|
i = val_compare(control, this);
|
||||||
|
if (!i)
|
||||||
|
return interpret(what->a2.p);
|
||||||
|
if (i==CMP_ERROR) {
|
||||||
|
i = val_in_range(control, this);
|
||||||
|
if (i==1)
|
||||||
|
return interpret(what->a2.p);
|
||||||
|
if (i==CMP_ERROR)
|
||||||
|
runtime( "incompatible types in case" );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
bug( "This can not happen (%x)\n", what->code );
|
||||||
|
}
|
||||||
|
return interpret_switch(what->next, control);
|
||||||
|
}
|
||||||
|
|
||||||
static struct f_val
|
static struct f_val
|
||||||
interpret(struct f_inst *what)
|
interpret(struct f_inst *what)
|
||||||
{
|
{
|
||||||
|
@ -155,11 +201,9 @@ interpret(struct f_inst *what)
|
||||||
case '~':
|
case '~':
|
||||||
TWOARGS;
|
TWOARGS;
|
||||||
res.type = T_BOOL;
|
res.type = T_BOOL;
|
||||||
if (((v1.type == T_INT) || (v1.type == T_IP)) && (v2.type == T_SET)) {
|
res.val.i = val_in_range(v1, v2);
|
||||||
res.val.i = !! find_tree(v2.val.t, v1);
|
if (res.val.i == CMP_ERROR)
|
||||||
break;
|
runtime( "~ applied on unknown type pair" );
|
||||||
}
|
|
||||||
runtime( "~ applied on unknown type pair" );
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Set to consant, a1 = type, a2 = value */
|
/* Set to consant, a1 = type, a2 = value */
|
||||||
|
@ -258,6 +302,10 @@ interpret(struct f_inst *what)
|
||||||
ONEARG;
|
ONEARG;
|
||||||
res = interpret(what->a2.p);
|
res = interpret(what->a2.p);
|
||||||
break;
|
break;
|
||||||
|
case 'sw': /* SWITCH alias CASE */
|
||||||
|
ONEARG;
|
||||||
|
interpret_switch(what->a2.p, v1);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
|
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue