From 41be4444f2f548c5cc135593b2c820180a22ff99 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Thu, 28 Oct 1999 21:03:36 +0000 Subject: [PATCH] switch() { } done right. --- Makefile | 4 ++-- bird.conf | 7 ++++-- conf/confbase.Y | 2 +- filter/config.Y | 40 +++++++++++++++------------------ filter/filter.c | 60 +++++++++++++++++++------------------------------ filter/tree.c | 2 +- 6 files changed, 50 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index a2bba642..2221101d 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,12 @@ objdir=obj -all depend: +all depend tags: $(MAKE) -C $(objdir) $@ clean: $(MAKE) -C $(objdir) clean - find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name depend -or -name .#* | xargs rm -f + find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name depend -or -name ".#*" | xargs rm -f distclean: clean rm -rf $(objdir) diff --git a/bird.conf b/bird.conf index b1220c32..3b8f6a7b 100644 --- a/bird.conf +++ b/bird.conf @@ -14,7 +14,7 @@ function callme (int arg1; int arg2;) case arg1 { 2: print "dva"; print "jeste jednou dva"; - [ 3 .. 5 ]: print "tri az pet"; + 3 .. 5: print "tri az pet"; else: print "neco jineho"; } } @@ -40,8 +40,11 @@ prefix px; print "Testing prefixes: 1.2.3.4/18 = " px; print "Testing pairs: (1,2) = " (1,2); + print "What will this do? " [ 1, 2, 1, 1, 1, 3, 4, 1, 1, 1, 5 ]; + print "Testing functions..."; - callme ( 1, 2 ); +# callme ( 1, 2 ); + callme ( 2, 2 ); callme ( 2, 2 ); callme ( 3, 2 ); callme ( 4, 2 ); diff --git a/conf/confbase.Y b/conf/confbase.Y index a6eb8764..b266d253 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -43,7 +43,7 @@ CF_DECLS %type expr bool pxlen datetime -%nonassoc '=' '<' '>' '~' ELSE IF '.' +%nonassoc '=' '<' '>' '~' IF ELSE '.' %left '+' '-' %left '*' '/' '%' %left '!' diff --git a/filter/config.Y b/filter/config.Y index 93854836..d5a9dca9 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -11,7 +11,6 @@ FIXME: whole system of paths, path ~ string, path.prepend(), path.originate FIXME: create community lists FIXME: access to dynamic attributes - FIXME: make case faster */ CF_HDR @@ -37,10 +36,10 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST, FILTER ) -%type term block cmds cmd function_body ifthen constant print_one print_list var_list switch_body +%type term block cmds cmd function_body ifthen constant print_one print_list var_list %type filter filter_body %type type break_command pair -%type set_item set_items +%type set_item set_items switch_body %type set_atom prefix prefix_s ipa %type decls function_params @@ -191,6 +190,20 @@ set_items: | set_items ',' set_item { $$ = $3; $$->left = $1; } ; +/* 2 shift/reduce conflicts here. Curable by replacing cmds with block which breaks syntax */ +switch_body: /* EMPTY */ { $$ = NULL; } + | set_item ':' cmds switch_body { + $$ = $1; + $$->data = $3; + $$->left = $4; + } + | ELSE ':' cmds { + $$ = f_new_tree(); + $$->from.type = T_VOID; + $$->to.type = T_VOID; + $$->data = $3; + } + ; constant: CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; } @@ -286,23 +299,6 @@ var_list: term { } ; -/* 2 shift/reduce conflicts here. Curable by replacing cmds with block which breaks syntax */ -switch_body: /* EMPTY */ { $$ = NULL; } - | term ':' cmds switch_body { - $$ = f_new_inst(); - $$->code = 'of'; - $$->a1.p = $1; - $$->a2.p = $3; - $$->next = $4; - } - | ELSE ':' cmds { - $$ = f_new_inst(); - $$->code = 'el'; - $$->a1.p = NULL; - $$->a2.p = $3; - } - ; - cmd: ifthen { $$ = $1; @@ -346,9 +342,9 @@ cmd: } | CASE term '{' switch_body '}' { $$ = f_new_inst(); - $$->code = 'sw'; + $$->code = 'SW'; $$->a1.p = $2; - $$->a2.p = $4; + $$->a2.p = build_tree( $4 ); } ; diff --git a/filter/filter.c b/filter/filter.c index f6b2d4be..dc8235ed 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -54,6 +54,13 @@ struct f_inst *startup_func = NULL; int val_compare(struct f_val v1, struct f_val v2) { + if ((v1.type == T_VOID) && (v2.type == T_VOID)) + return 0; + if (v1.type == T_VOID) /* Hack for else */ + return -1; + if (v2.type == T_VOID) + return 1; + if (v1.type != v2.type) return CMP_ERROR; switch (v1.type) { @@ -64,7 +71,7 @@ val_compare(struct f_val v1, struct f_val v2) return 1; case T_IP: return ipa_compare(v1.val.ip, v2.val.ip); - default: return CMP_ERROR; + default: { printf( "Error comparing\n" ); return CMP_ERROR; } } } @@ -114,40 +121,6 @@ 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 interpret(struct f_inst *what) { @@ -309,9 +282,22 @@ interpret(struct f_inst *what) ONEARG; res = interpret(what->a2.p); break; - case 'sw': /* SWITCH alias CASE */ + case 'SW': ONEARG; - interpret_switch(what->a2.p, v1); + { + struct f_tree *t = find_tree(what->a2.p, v1); + if (!t) { + v1.type = T_VOID; + t = find_tree(what->a2.p, v1); + if (!t) { + printf( "No else statement?\n "); + break; + } + } + if (!t->data) + die( "Impossible: no code associated!\n" ); + return interpret(t->data); + } break; case 'iM': /* IP.MASK(val) */ TWOARGS_C; diff --git a/filter/tree.c b/filter/tree.c index ea1f18f2..43888f0b 100644 --- a/filter/tree.c +++ b/filter/tree.c @@ -73,7 +73,7 @@ struct f_tree * find_tree(struct f_tree *t, struct f_val val) { if (!t) - return 0; + return NULL; if ((val_compare(t->from, val) != 1) && (val_compare(t->to, val) != -1)) return t;