summaryrefslogtreecommitdiffstats
path: root/src/scanner.c
diff options
context:
space:
mode:
authorAuke Booij <auke@tulcod.com>2015-10-26 19:39:52 +0000
committerBryce Harrington <bryce@osg.samsung.com>2015-11-04 14:51:43 -0800
commit1771299a5a965c1f95c18ef795c29db876133a81 (patch)
treecc64a942ed5b7ad3635b94f8ef408dee902d3ad0 /src/scanner.c
parentprotocol: specify enum and bitfield attributes (diff)
downloadwayland-1771299a5a965c1f95c18ef795c29db876133a81.tar
wayland-1771299a5a965c1f95c18ef795c29db876133a81.tar.gz
wayland-1771299a5a965c1f95c18ef795c29db876133a81.tar.bz2
wayland-1771299a5a965c1f95c18ef795c29db876133a81.tar.lz
wayland-1771299a5a965c1f95c18ef795c29db876133a81.tar.xz
wayland-1771299a5a965c1f95c18ef795c29db876133a81.tar.zst
wayland-1771299a5a965c1f95c18ef795c29db876133a81.zip
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: Auke Booij <auke@tulcod.com> Reviewed-by: Bryce Harrington <bryce@osg.samsung.com> Reviewed-by: Nils Chr. Brause <nilschrbrause@googlemail.com>
Diffstat (limited to 'src/scanner.c')
-rw-r--r--src/scanner.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/scanner.c b/src/scanner.c
index b231d02..8ecdd56 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -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);
@@ -701,6 +724,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)
{
struct parse_context *ctx = data;
@@ -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);
+
}
}