Commit 1771299a authored by Auke Booij's avatar Auke Booij Committed by Bryce Harrington

scanner: enforce correct argument type for enums

The scanner now checks whether arguments that have an associated
<enum> have the right type.
An argument with an enum attribute must be of type int or uint,
and if the <enum> with that name has the bitfield attribute
set to true, then the argument must be of type uint.

Changes since v3:
 - Remove useless allow_null check
 - Switch to using bool
 - Clearer message on errorous input
 - Minor formatting fix
Signed-off-by: default avatarAuke Booij <auke@tulcod.com>
Reviewed-by: default avatarBryce Harrington <bryce@osg.samsung.com>
Reviewed-by: default avatarNils Chr. Brause <nilschrbrause@googlemail.com>
parent 851614fa
......@@ -128,6 +128,7 @@ struct arg {
char *interface_name;
struct wl_list link;
char *summary;
char *enumeration_name;
};
struct enumeration {
......@@ -136,6 +137,7 @@ struct enumeration {
struct wl_list entry_list;
struct wl_list link;
struct description *description;
bool bitfield;
};
struct entry {
......@@ -540,6 +542,8 @@ start_element(void *data, const char *element_name, const char **atts)
const char *summary = NULL;
const char *since = NULL;
const char *allow_null = NULL;
const char *enumeration_name = NULL;
const char *bitfield = NULL;
int i, version = 0;
ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
......@@ -562,6 +566,10 @@ start_element(void *data, const char *element_name, const char **atts)
since = atts[i + 1];
if (strcmp(atts[i], "allow-null") == 0)
allow_null = atts[i + 1];
if (strcmp(atts[i], "enum") == 0)
enumeration_name = atts[i + 1];
if (strcmp(atts[i], "bitfield") == 0)
bitfield = atts[i + 1];
}
ctx->character_data_length = 0;
......@@ -655,6 +663,11 @@ start_element(void *data, const char *element_name, const char **atts)
"allow-null is only valid for objects, strings, and arrays");
}
if (enumeration_name == NULL || strcmp(enumeration_name, "") == 0)
arg->enumeration_name = NULL;
else
arg->enumeration_name = xstrdup(enumeration_name);
if (summary)
arg->summary = xstrdup(summary);
......@@ -665,6 +678,16 @@ start_element(void *data, const char *element_name, const char **atts)
fail(&ctx->loc, "no enum name given");
enumeration = create_enumeration(name);
if (bitfield == NULL || strcmp(bitfield, "false") == 0)
enumeration->bitfield = false;
else if (strcmp(bitfield, "true") == 0)
enumeration->bitfield = true;
else
fail(&ctx->loc,
"invalid value (%s) for bitfield attribute (only true/false are accepted)",
bitfield);
wl_list_insert(ctx->interface->enumeration_list.prev,
&enumeration->link);
......@@ -700,6 +723,46 @@ start_element(void *data, const char *element_name, const char **atts)
}
}
static void
verify_arguments(struct parse_context *ctx, struct wl_list *messages, struct wl_list *enumerations)
{
struct message *m;
wl_list_for_each(m, messages, link) {
struct arg *a;
wl_list_for_each(a, &m->arg_list, link) {
struct enumeration *e, *f;
if (!a->enumeration_name)
continue;
f = NULL;
wl_list_for_each(e, enumerations, link) {
if(strcmp(e->name, a->enumeration_name) == 0)
f = e;
}
if (f == NULL)
fail(&ctx->loc,
"could not find enumeration %s",
a->enumeration_name);
switch (a->type) {
case INT:
if (f->bitfield)
fail(&ctx->loc,
"bitfield-style enum must only be referenced by uint");
break;
case UNSIGNED:
break;
default:
fail(&ctx->loc,
"enumeration-style argument has wrong type");
}
}
}
}
static void
end_element(void *data, const XML_Char *name)
{
......@@ -723,6 +786,12 @@ end_element(void *data, const XML_Char *name)
ctx->enumeration->name);
}
ctx->enumeration = NULL;
} else if (strcmp(name, "interface") == 0) {
struct interface *i = ctx->interface;
verify_arguments(ctx, &i->request_list, &i->enumeration_list);
verify_arguments(ctx, &i->event_list, &i->enumeration_list);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment