diff options
author | Patrick McHardy <kaber@trash.net> | 2013-04-15 00:36:36 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2013-04-18 15:28:46 +0200 |
commit | 84cf34938294e404fd7e9ebe1a630fe868ae22da (patch) | |
tree | 040ef41daf17fee350c294ed19d409d1a651a299 /src/datatype.c | |
parent | a711ab22a58504e52c33f5fd939643002d7e6a81 (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.c | 37 |
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); +} |