summaryrefslogtreecommitdiffstats
path: root/src/datatype.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2013-04-15 00:36:36 +0200
committerPatrick McHardy <kaber@trash.net>2013-04-18 15:28:46 +0200
commit84cf34938294e404fd7e9ebe1a630fe868ae22da (patch)
tree040ef41daf17fee350c294ed19d409d1a651a299 /src/datatype.c
parenta711ab22a58504e52c33f5fd939643002d7e6a81 (diff)
expr: fix concat expression type propagation
Dynamically instantiate a data type to represent all types of a concatenation and use that for type propagation.
Diffstat (limited to 'src/datatype.c')
-rw-r--r--src/datatype.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/datatype.c b/src/datatype.c
index e87de418..3a2f19d8 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -23,6 +23,7 @@
#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,
@@ -642,3 +643,39 @@ const struct datatype time_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);
+}