struct expr **res);
extern void datatype_print(const struct expr *expr);
+static inline bool datatype_equal(const struct datatype *d1,
+ const struct datatype *d2)
+{
+ return d1->type == d2->type;
+}
+
/**
* struct symbolic_constant - symbol <-> constant mapping
*
extern const struct datatype mark_type;
extern const struct datatype time_type;
+extern const struct datatype *concat_type_alloc(const struct expr *expr);
+extern void concat_type_destroy(const struct datatype *dtype);
+
#endif /* NFTABLES_DATATYPE_H */
#include <erec.h>
static const struct datatype *datatypes[TYPE_MAX + 1] = {
+ [TYPE_INVALID] = &invalid_type,
[TYPE_VERDICT] = &verdict_type,
[TYPE_BITMASK] = &bitmask_type,
[TYPE_INTEGER] = &integer_type,
.basetype = &integer_type,
.print = time_type_print,
};
+
+static struct error_record *concat_type_parse(const struct expr *sym,
+ struct expr **res)
+{
+ return error(&sym->location, "invalid data type, expected %s",
+ sym->dtype->desc);
+}
+
+const struct datatype *concat_type_alloc(const struct expr *expr)
+{
+ struct datatype *dtype;
+ struct expr *i;
+ char desc[256] = "concatenation of ";
+ unsigned int type = 0;
+
+ list_for_each_entry(i, &expr->expressions, list) {
+ if (type != 0)
+ strncat(desc, ", ", sizeof(desc) - strlen(desc) - 1);
+ strncat(desc, i->dtype->desc, sizeof(desc) - strlen(desc) - 1);
+
+ type <<= 8;
+ type |= i->dtype->type;
+ }
+
+ dtype = xzalloc(sizeof(*dtype));
+ dtype->type = type;
+ dtype->desc = xstrdup(desc);
+ dtype->parse = concat_type_parse;
+
+ return dtype;
+}
+
+void concat_type_destroy(const struct datatype *dtype)
+{
+ xfree(dtype);
+}
static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
{
- unsigned int flags = EXPR_F_CONSTANT;
+ const struct datatype *dtype = ctx->ectx.dtype, *tmp;
+ unsigned int type = dtype ? dtype->type : 0;
+ unsigned int flags = EXPR_F_CONSTANT | EXPR_F_SINGLETON;
struct expr *i, *next;
+ unsigned int n;
+ n = 1;
list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
+ tmp = datatype_lookup((type >> 8 * ((*expr)->size - n)) & 0xff);
+ expr_set_context(&ctx->ectx, tmp, tmp->size);
+
if (list_member_evaluate(ctx, &i) < 0)
return -1;
flags &= i->flags;
+
+ n++;
}
(*expr)->flags |= flags;
+ (*expr)->dtype = concat_type_alloc(*expr);
+
+ expr_set_context(&ctx->ectx, (*expr)->dtype, (*expr)->len);
+
return 0;
}
if (right->ops->type == EXPR_SET)
right = rel->right =
implicit_set_declaration(ctx, left->dtype, left->len, right);
- else if (left->dtype != right->dtype)
+ else if (!datatype_equal(left->dtype, right->dtype))
return expr_binary_error(ctx, right, left,
"datatype mismatch, expected %s, "
"set has type %s",
left = rel->left;
break;
case OP_EQ:
- if (left->dtype != right->dtype)
+ if (!datatype_equal(left->dtype, right->dtype))
return expr_binary_error(ctx, right, left,
"datatype mismatch, expected %s, "
"expression has type %s",
case EXPR_META:
payload_ctx_update_meta(&ctx->pctx, rel);
break;
+ case EXPR_CONCAT:
+ return 0;
default:
break;
}
case OP_NEQ:
case OP_FLAGCMP:
- if (left->dtype != right->dtype)
+ if (!datatype_equal(left->dtype, right->dtype))
return expr_binary_error(ctx, right, left,
"datatype mismatch, expected %s, "
"expression has type %s",
case OP_GT:
case OP_LTE:
case OP_GTE:
- if (left->dtype != right->dtype)
+ if (datatype_equal(left->dtype, right->dtype))
return expr_binary_error(ctx, right, left,
"datatype mismatch, expected %s, "
"expression has type %s",
return -1;
break;
case OP_RANGE:
- if (left->dtype != right->dtype)
+ if (datatype_equal(left->dtype, right->dtype))
return expr_binary_error(ctx, right, left,
"datatype mismatch, expected %s, "
"expression has type %s",
list_del(&expr->list);
}
+static void concat_expr_destroy(struct expr *expr)
+{
+ concat_type_destroy(expr->dtype);
+ compound_expr_destroy(expr);
+}
+
static void concat_expr_print(const struct expr *expr)
{
compound_expr_print(expr, " . ");
.name = "concat",
.print = concat_expr_print,
.clone = compound_expr_clone,
- .destroy = compound_expr_destroy,
+ .destroy = concat_expr_destroy,
};
struct expr *concat_expr_alloc(const struct location *loc)