[PATCH wayland v2 1/2] scanner: refactor creating objects
Bryce Harrington
bryce at osg.samsung.com
Wed Jul 29 20:03:09 PDT 2015
On Mon, Jul 27, 2015 at 09:17:15AM +0200, Marek Chalupa wrote:
> Hi,
> thanks for review.
>
> On 07/23/2015 08:41 PM, Bryce Harrington wrote:
> >On Thu, Jul 23, 2015 at 07:39:30AM +0200, Marek Chalupa wrote:
> >>wrap creating and initializing objects (structures)
> >>into functions and use them in the code.
> >>
> >>Signed-off-by: Marek Chalupa <mchqwerty at gmail.com>
> >>---
> >> src/scanner.c | 158 ++++++++++++++++++++++++++++++++++++++--------------------
> >> 1 file changed, 105 insertions(+), 53 deletions(-)
> >>
> >>diff --git a/src/scanner.c b/src/scanner.c
> >>index 7d8cfb9..85c283b 100644
> >>--- a/src/scanner.c
> >>+++ b/src/scanner.c
> >>@@ -1,6 +1,7 @@
> >> /*
> >> * Copyright © 2008-2011 Kristian Høgsberg
> >> * Copyright © 2011 Intel Corporation
> >>+ * Copyright © 2015 Red Hat, Inc.
> >> *
> >> * Permission is hereby granted, free of charge, to any person obtaining
> >> * a copy of this software and associated documentation files (the
> >>@@ -315,6 +316,102 @@ is_nullable_type(struct arg *arg)
> >> }
> >> }
> >>
> >>+static struct message *
> >>+create_message(struct location loc, const char *name)
> >>+{
> >>+ struct message *message;
> >>+
> >>+ message = xmalloc(sizeof *message);
> >>+ message->loc = loc;
> >>+ message->name = xstrdup(name);
> >>+ message->uppercase_name = uppercase_dup(name);
> >>+ wl_list_init(&message->arg_list);
> >>+ message->arg_count = 0;
> >>+ message->new_id_count = 0;
> >>+ message->description = NULL;
> >>+
> >>+ return message;
> >>+}
> >
> >The message structure has a few more fields, that this constructor
> >leaves uninitialized. I don't know if that's ok or not.
>
> These are initialized right after create_message().
> I didn't want to initialize them to some default value and in the very
> next few lines of code rewrite them again.
>
> >
> >struct message {
> > struct location loc;
> > char *name;
> > char *uppercase_name;
> > struct wl_list arg_list;
> >--> struct wl_list link;
> > int arg_count;
> > int new_id_count;
> >--> int type_index;
> >--> int all_null;
> >--> int destructor;
> >--> int since;
> > struct description *description;
> >};
> >
> >One thing you might consider is rather than xmalloc, to use calloc
> >which will guarantee all members are set to 0 initially. calloc can
> >actually be more efficient than manually setting fields to 0 since the
> >kernel can give us pre-zero'd memory if it has any.
>
> Yes, but number of items in the structures that are initialized to
> 0's is not so big. struct message has 3 fields initialized to 0 out
> of 12, struct arg 2 of 6, ... (see the end of the e-mail)
> >
> >Here's what we use in weston:
> >
> ># from shared/zalloc.h
> >static inline void *
> >zalloc(size_t size)
> >{
> > return calloc(1, size);
> >}
> >
> ># From window.c
> >void *
> >xzalloc(size_t s)
> >{
> > return fail_on_null(zalloc(s));
> >}
> >
> >With these definitions you could essentially s/xmalloc/xzalloc/
> >throughout the scanner code, and then drop any lines that just
> >initialize member fields to NULL or 0, as they will be redundant.
> >
> >>+
> >>+static struct arg *
> >>+create_arg(const char *name, const char *type)
> >>+{
> >>+ struct arg *arg;
> >>+
> >>+ arg = xmalloc(sizeof *arg);
> >>+ arg->name = xstrdup(name);
> >>+ arg->summary = NULL;
> >>+ arg->interface_name = NULL;
> >
> >nullable isn't initialized
>
> initialized again right after create_arg
>
> >
> >>+ if (strcmp(type, "int") == 0)
> >>+ arg->type = INT;
> >>+ else if (strcmp(type, "uint") == 0)
> >>+ arg->type = UNSIGNED;
> >>+ else if (strcmp(type, "fixed") == 0)
> >>+ arg->type = FIXED;
> >>+ else if (strcmp(type, "string") == 0)
> >>+ arg->type = STRING;
> >>+ else if (strcmp(type, "array") == 0)
> >>+ arg->type = ARRAY;
> >>+ else if (strcmp(type, "fd") == 0)
> >>+ arg->type = FD;
> >>+ else if (strcmp(type, "new_id") == 0)
> >>+ arg->type = NEW_ID;
> >>+ else if (strcmp(type, "object") == 0)
> >>+ arg->type = OBJECT;
> >>+ else
> >
> >should free(arg) at this point...
>
> Yes, has this in the patch no. 2, but it should be here
>
> >
> >>+ return NULL;
> >>+
> >>+ return arg;
> >>+}
> >
> >It's a little inconsistent that create_arg can return NULL when all the
> >other create_* routines are being guaranteed to never return NULL.
> >
> >Since the only action that appears to be taken when this happens is to
> >fail and terminate the program, this routine could just call
> >fail_on_null(NULL) when it hits the unknown arg type in the if structure
> >above. That would make behaviors consistent.
> >
> >Alternatively, the arg structure could be given an error indicator, and
> >then the caller check that (rather than arg == NULL). But I think this
> >is probably overkill.
>
> Actually, this returns NULL only because I didn't want to pass to
> ctx->loc to create_arg. I think that quite clear solution will be
> to move setting the argument type to self-standing function, that
> can return boolean.
>
> >
> >>+static struct enumeration *
> >>+create_enumeration(const char *name)
> >>+{
> >>+ struct enumeration *enumeration;
> >>+
> >>+ enumeration = xmalloc(sizeof *enumeration);
> >>+ enumeration->name = xstrdup(name);
> >>+ enumeration->uppercase_name = uppercase_dup(name);
> >>+ enumeration->description = NULL;
> >>+
> >>+ wl_list_init(&enumeration->entry_list);
> >>+
> >>+ return enumeration;
> >>+}
> >>+
> >>+static struct entry *
> >>+create_entry(const char *name, const char *value)
> >>+{
> >>+ struct entry *entry;
> >>+
> >>+ entry = xmalloc(sizeof *entry);
> >>+ entry->name = xstrdup(name);
> >>+ entry->uppercase_name = uppercase_dup(name);
> >>+ entry->value = xstrdup(value);
> >
> >summary isn't initialized
> >
> >>+
> >>+ return entry;
> >>+}
> >>+
> >>+static struct interface *
> >>+create_interface(struct location loc, const char *name, int version)
> >>+{
> >>+ struct interface *interface;
> >>+
> >>+ interface = xmalloc(sizeof *interface);
> >>+ interface->loc = loc;
> >>+ interface->name = xstrdup(name);
> >>+ interface->uppercase_name = uppercase_dup(name);
> >>+ interface->version = version;
> >>+ interface->description = NULL;
> >>+ interface->since = 1;
> >>+ wl_list_init(&interface->request_list);
> >>+ wl_list_init(&interface->event_list);
> >>+ wl_list_init(&interface->enumeration_list);
> >>+
> >>+ return interface;
> >>+}
> >>+
> >> static void
> >> start_element(void *data, const char *element_name, const char **atts)
> >> {
> >>@@ -376,32 +473,16 @@ start_element(void *data, const char *element_name, const char **atts)
> >> if (version == 0)
> >> fail(&ctx->loc, "no interface version given");
> >>
> >>- interface = xmalloc(sizeof *interface);
> >>- interface->loc = ctx->loc;
> >>- interface->name = xstrdup(name);
> >>- interface->uppercase_name = uppercase_dup(name);
> >>- interface->version = version;
> >>- interface->description = NULL;
> >>- interface->since = 1;
> >>- wl_list_init(&interface->request_list);
> >>- wl_list_init(&interface->event_list);
> >>- wl_list_init(&interface->enumeration_list);
> >>+ interface = create_interface(ctx->loc, name, version);
> >>+ ctx->interface = interface;
> >> wl_list_insert(ctx->protocol->interface_list.prev,
> >> &interface->link);
> >>- ctx->interface = interface;
> >> } else if (strcmp(element_name, "request") == 0 ||
> >> strcmp(element_name, "event") == 0) {
> >> if (name == NULL)
> >> fail(&ctx->loc, "no request name given");
> >>
> >>- message = xmalloc(sizeof *message);
> >>- message->loc = ctx->loc;
> >>- message->name = xstrdup(name);
> >>- message->uppercase_name = uppercase_dup(name);
> >>- wl_list_init(&message->arg_list);
> >>- message->arg_count = 0;
> >>- message->new_id_count = 0;
> >>- message->description = NULL;
> >>+ message = create_message(ctx->loc, name);
> >>
> >> if (strcmp(element_name, "request") == 0)
> >> wl_list_insert(ctx->interface->request_list.prev,
> >>@@ -440,28 +521,9 @@ start_element(void *data, const char *element_name, const char **atts)
> >> if (name == NULL)
> >> fail(&ctx->loc, "no argument name given");
> >>
> >>- arg = xmalloc(sizeof *arg);
> >>- arg->name = xstrdup(name);
> >>-
> >>- if (strcmp(type, "int") == 0)
> >>- arg->type = INT;
> >>- else if (strcmp(type, "uint") == 0)
> >>- arg->type = UNSIGNED;
> >>- else if (strcmp(type, "fixed") == 0)
> >>- arg->type = FIXED;
> >>- else if (strcmp(type, "string") == 0)
> >>- arg->type = STRING;
> >>- else if (strcmp(type, "array") == 0)
> >>- arg->type = ARRAY;
> >>- else if (strcmp(type, "fd") == 0)
> >>- arg->type = FD;
> >>- else if (strcmp(type, "new_id") == 0) {
> >>- arg->type = NEW_ID;
> >>- } else if (strcmp(type, "object") == 0) {
> >>- arg->type = OBJECT;
> >>- } else {
> >>+ arg = create_arg(name, type);
> >>+ if (!arg)
> >> fail(&ctx->loc, "unknown type (%s)", type);
> >>- }
> >>
> >> switch (arg->type) {
> >> case NEW_ID:
> >>@@ -472,8 +534,6 @@ start_element(void *data, const char *element_name, const char **atts)
> >> case OBJECT:
> >> if (interface_name)
> >> arg->interface_name = xstrdup(interface_name);
> >>- else
> >>- arg->interface_name = NULL;
> >> break;
> >> default:
> >> if (interface_name != NULL)
> >>@@ -491,7 +551,6 @@ start_element(void *data, const char *element_name, const char **atts)
> >> if (allow_null != NULL && !is_nullable_type(arg))
> >> fail(&ctx->loc, "allow-null is only valid for objects, strings, and arrays");
> >>
> >>- arg->summary = NULL;
> >> if (summary)
> >> arg->summary = xstrdup(summary);
> >>
> >>@@ -501,12 +560,7 @@ start_element(void *data, const char *element_name, const char **atts)
> >> if (name == NULL)
> >> fail(&ctx->loc, "no enum name given");
> >>
> >>- enumeration = xmalloc(sizeof *enumeration);
> >>- enumeration->name = xstrdup(name);
> >>- enumeration->uppercase_name = uppercase_dup(name);
> >>- enumeration->description = NULL;
> >>- wl_list_init(&enumeration->entry_list);
> >>-
> >>+ enumeration = create_enumeration(name);
> >> wl_list_insert(ctx->interface->enumeration_list.prev,
> >> &enumeration->link);
> >>
> >>@@ -515,10 +569,8 @@ start_element(void *data, const char *element_name, const char **atts)
> >> if (name == NULL)
> >> fail(&ctx->loc, "no entry name given");
> >>
> >>- entry = xmalloc(sizeof *entry);
> >>- entry->name = xstrdup(name);
> >>- entry->uppercase_name = uppercase_dup(name);
> >>- entry->value = xstrdup(value);
> >>+ entry = create_entry(name, value);
> >>+
> >> if (summary)
> >> entry->summary = xstrdup(summary);
> >> else
> >>--
> >>2.4.3
> >>
> >>_______________________________________________
> >>wayland-devel mailing list
> >>wayland-devel at lists.freedesktop.org
> >>http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
> I'm not against using xzalloc and initialize all new memory to 0, it
> can make the code more clean. But the intention of this patch was to
> 'move' the current code into the functions, without any functional
> changes - if you would inline the create_* functions, you'd get the
> old code (well, except for like 3-5 lines). There is a lot of places
> with nested if's that are setting the field to either 0 or 1, so
> initializing all to 0's and then removing the branches that set the
> fields to 0 could introduce bugs. Therefore I think it would be
> better to do it as a follow up, wouldn't be?
A followup patch to add the xzalloc cleanup would be fine.
I think that'd be more robust and simplify the create routines a good bit.
Bryce
More information about the wayland-devel
mailing list