aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-10-04 01:22:27 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-10-04 01:22:27 +0300
commit11db69e6d2b292df96845515f7df0e850b60c125 (patch)
tree9c4bb3a47ead03b6093ceed3e0142fc259a91de0 /lib
parent256d8b3572532af87ea5b28379cee709ad44cea6 (diff)
downloadeclat-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.c170
-rw-r--r--lib/forlan.h5
-rw-r--r--lib/forlangrm.y15
-rw-r--r--lib/forlanlex.l2
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();

Return to:

Send suggestions and report system problems to the System administrator.