diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-10-04 01:22:27 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-10-04 01:22:27 +0300 |
commit | 11db69e6d2b292df96845515f7df0e850b60c125 (patch) | |
tree | 9c4bb3a47ead03b6093ceed3e0142fc259a91de0 /lib | |
parent | 256d8b3572532af87ea5b28379cee709ad44cea6 (diff) | |
download | eclat-11db69e6d2b292df96845515f7df0e850b60c125.tar.gz eclat-11db69e6d2b292df96845515f7df0e850b60c125.tar.bz2 |
Implement eq/ne comparisons in forlan; Implement describe-security-groups command.
* etc/Makefile.am: Add new file.
* etc/describe-security-groups.fln: New file.
* lib/forlan.c: Implement equality and inequality comparisons.
* lib/forlan.h (forlan_opcode_eq)
(forlan_opcode_ne): New opcodes.
(FORLAN_NTYPES): New constants.
* lib/forlangrm.y: Add equality and inequality productions.
* lib/forlanlex.l: New tokens: == and !=
* src/dscrsecgrps-cl.opt: New file.
* src/dscrsecgrps.c: New file.
* src/Makefile.am: Add new files.
* src/eclat.c: Implement describe-security-groups
* src/eclat.h (eclat_describe_security_groups): New proto.
* src/cretags.c: Fix memory leaks.
* src/deltags.c: Likewise.
* src/dscrtags.c: Likewise.
* tests/describe-security-groups.at: New test case.
* tests/testsuite.at: Include new test case.
* tests/Makefile.am: Add new test case.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/forlan.c | 170 | ||||
-rw-r--r-- | lib/forlan.h | 5 | ||||
-rw-r--r-- | lib/forlangrm.y | 15 | ||||
-rw-r--r-- | lib/forlanlex.l | 2 |
4 files changed, 142 insertions, 50 deletions
diff --git a/lib/forlan.c b/lib/forlan.c index 74b03a3..f1d49d7 100644 --- a/lib/forlan.c +++ b/lib/forlan.c @@ -97,103 +97,161 @@ valtypestr(enum forlan_value_type t) } } -static void -coerce_retval(forlan_eval_env_t env, int c) +static int +value_boolean(struct forlan_value *val) { - enum forlan_value_type t; - struct grecs_node *node; + int res; - switch (c) { - case 's': - t = forlan_value_literal; + switch (val->type) { + case forlan_value_void: + err("controlling expression returned void, aborting"); + abort(); + + case forlan_value_node: + res = val->v.node != NULL; break; - case 'n': - t = forlan_value_node; + + case forlan_value_literal: + res = val->v.string != NULL && val->v.string[0] != 0; break; - case 'b': - t = forlan_value_boolean; + + case forlan_value_boolean: + res = val->v.num; break; - case ' ': - t = forlan_value_void; + + default: + abort(); } + return res; +} + +int +retval_boolean(forlan_eval_env_t env) +{ + return value_boolean(&env->retval); +} - if (t == env->retval.type) +static void +coerce_value(forlan_eval_env_t env, struct forlan_value *val, + enum forlan_value_type t) +{ + struct grecs_node *node; + + if (t == val->type) return; if (t == forlan_value_void) { - free_value(&env->retval); - env->retval.type = forlan_value_void; + free_value(val); + val->type = forlan_value_void; return; } - if (env->retval.type == forlan_value_void) { + if (val->type == forlan_value_void) { err("can't coerce %s to %s", - valtypestr(env->retval.type), + valtypestr(val->type), valtypestr(t)); abort(); } if (t == forlan_value_boolean) { - int res = retval_boolean(env); - free_value(&env->retval); - env->retval.type = forlan_value_boolean; - env->retval.v.num = res; + int res = value_boolean(val); + free_value(val); + val->type = forlan_value_boolean; + val->v.num = res; return; } /* Convert between string and node */ - switch (env->retval.type) { + switch (val->type) { case forlan_value_literal: - node = grecs_find_node(env->tree, env->retval.v.string); - free(env->retval.v.string); - env->retval.v.node = node; + node = grecs_find_node(env->tree, val->v.string); + free(val->v.string); + val->v.node = node; break; case forlan_value_node: - if (env->retval.v.node->type == grecs_node_stmt) { + if (val->v.node->type == grecs_node_stmt) { struct grecs_txtacc *acc = grecs_txtacc_create(); - grecs_txtacc_format_value(env->retval.v.node->v.value, + grecs_txtacc_format_value(val->v.node->v.value, 0, acc); - env->retval.v.string = grecs_txtacc_finish(acc, 1); + grecs_txtacc_grow_char(acc, 0); + val->v.string = grecs_txtacc_finish(acc, 1); grecs_txtacc_free(acc); } else - env->retval.v.string = grecs_strdup(""); + val->v.string = grecs_strdup(""); break; default: abort(); } - env->retval.type = t; + val->type = t; } + +static void +coerce_retval(forlan_eval_env_t env, int c) +{ + enum forlan_value_type t; + + switch (c) { + case 's': + t = forlan_value_literal; + break; + case 'n': + t = forlan_value_node; + break; + case 'b': + t = forlan_value_boolean; + break; + case ' ': + t = forlan_value_void; + } + coerce_value(env, &env->retval, t); +} + +#define T_E -1 +#define T_V forlan_value_void +#define T_N forlan_value_node +#define T_S forlan_value_literal +#define T_B forlan_value_boolean + +enum forlan_value_type convtab[FORLAN_NTYPES][FORLAN_NTYPES] = { + /* T_V T_N T_S T_B */ +/* T_V */ { T_E, T_E, T_E, T_E }, +/* T_N */ { T_E, T_S, T_S, T_B }, +/* T_S */ { T_E, T_S, T_S, T_B }, +/* T_B */ { T_E, T_B, T_B, T_B } +}; -int -retval_boolean(forlan_eval_env_t env) +static int +values_equal(forlan_eval_env_t env, + struct forlan_value *a, struct forlan_value *b) { int res; - - switch (env->retval.type) { - case forlan_value_void: - err("controlling expression returned void, aborting"); - abort(); + enum forlan_value_type t; - case forlan_value_node: - res = env->retval.v.node != NULL; - break; + t = convtab[a->type][b->type]; + if (t == T_E) { + err("incompatible values for comparison: %s, %s", + valtypestr(a->type), + valtypestr(b->type)); + abort(); + } + coerce_value(env, a, t); + coerce_value(env, b, t); - case forlan_value_literal: - res = env->retval.v.string != NULL && - env->retval.v.string[0] != 0; + switch (t) { + case T_S: + res = strcmp(a->v.string, b->v.string) == 0; break; - - case forlan_value_boolean: - res = env->retval.v.num; + case T_B: + res = !!a->v.num == !!b->v.num; break; - default: abort(); } return res; } + void eval_func(forlan_eval_env_t env, union forlan_node *node); void eval_last(forlan_eval_env_t env, union forlan_node *node); @@ -460,6 +518,7 @@ void eval_expr(forlan_eval_env_t env, union forlan_node *node) { int res; + struct forlan_value lval; free_value(&env->retval); switch (node->expr.opcode) { @@ -486,7 +545,20 @@ eval_expr(forlan_eval_env_t env, union forlan_node *node) env->retval.type = forlan_value_boolean; env->retval.v.num = !res; break; - + + case forlan_opcode_eq: + case forlan_opcode_ne: + forlan_eval(env, node->expr.arg[0]); + copy_value(&lval, &env->retval); + forlan_eval(env, node->expr.arg[1]); + res = values_equal(env, &lval, &env->retval); + free_value(&lval); + free_value(&env->retval); + env->retval.type = forlan_value_boolean; + env->retval.v.num = node->expr.opcode == forlan_opcode_eq ? + res : !res; + break; + default: abort(); } diff --git a/lib/forlan.h b/lib/forlan.h index 424cea8..0670480 100644 --- a/lib/forlan.h +++ b/lib/forlan.h @@ -123,7 +123,9 @@ enum forlan_opcode { forlan_opcode_node, /* Evaluate node, set 'last' */ forlan_opcode_and, /* Boolean AND */ forlan_opcode_or, /* Boolean OR */ - forlan_opcode_not /* Boolean NOT */ + forlan_opcode_not, /* Boolean NOT */ + forlan_opcode_eq, /* Equality */ + forlan_opcode_ne /* Inequality */ }; /* Boolean expression */ @@ -164,6 +166,7 @@ enum forlan_value_type { forlan_value_literal, forlan_value_boolean }; +#define FORLAN_NTYPES 4 struct forlan_value { enum forlan_value_type type; diff --git a/lib/forlangrm.y b/lib/forlangrm.y index eb7fc6f..5c91f1a 100644 --- a/lib/forlangrm.y +++ b/lib/forlangrm.y @@ -64,6 +64,7 @@ free_comp(void *p) %left OR %left AND +%nonassoc EQ NE %left NOT %type <node> stmt stmt_cond stmt_expr stmt_blk cond bool node funcall arg rval @@ -152,6 +153,20 @@ bool : node $$->expr.opcode = forlan_opcode_not; $$->expr.arg[0] = $2; } + | node EQ node + { + $$ = forlan_node_create(forlan_type_expr); + $$->expr.opcode = forlan_opcode_eq; + $$->expr.arg[0] = $1; + $$->expr.arg[1] = $3; + } + | node NE node + { + $$ = forlan_node_create(forlan_type_expr); + $$->expr.opcode = forlan_opcode_ne; + $$->expr.arg[0] = $1; + $$->expr.arg[1] = $3; + } | '(' bool ')' { $$ = $2; diff --git a/lib/forlanlex.l b/lib/forlanlex.l index 8b3d29a..8df6d80 100644 --- a/lib/forlanlex.l +++ b/lib/forlanlex.l @@ -83,6 +83,8 @@ continue return CONTINUE; ! return NOT; "&&" return AND; "||" return OR; +"==" return EQ; +"!=" return NE; {IDC}{IDC}* { grecs_line_begin(); grecs_line_add(yytext, yyleng); yylval.string = grecs_line_finish(); |