[waffle] [PATCH 1/4] waffle: put waffle_enum items in a macro

Chad Versace chad.versace at intel.com
Tue May 5 21:18:52 PDT 2015


On Thu 23 Apr 2015, Emil Velikov wrote:
> On 23 April 2015 at 02:07, Frank Henigman <fjhenigman at google.com> wrote:
> > On Wed, Apr 22, 2015 at 8:09 PM, Jordan Justen
> > <jordan.l.justen at intel.com> wrote:
> >> On 2015-04-22 11:03:47, Frank Henigman wrote:
> >>> List all waffle_enum items in a big #define to avoid duplicating
> >>> the list when a case is needed for each item, e.g. enum to string.
> >>
> >> This looks kind of yucky. :)
> >>
> >> When you recently mentioned the idea of changing wflinfo to be written
> >> in python, it made me think about python bindings for waffle.
> >>
> >> This lead me to think that it might be nice if the waffle API was
> >> defined by something like XML. This would allow us to generate
> >> waffle.h, python bindings, and things like this enum to string
> >> mapping.
> >>
> >> We do something similar (enum to string mapping) on the OpenGL API in
> >> piglit.
> >>
> >> -Jordan
> >
> > There seem to be three ways to generate the desired code:
> > - manually repeating lists of stuff

Major yuk! I hate all the repetition in Waffle's codebase. I hate that
we have to sometimes add stuff in 3 separate locations.

> > - with the preprocessor, as in this patch

Doable... But, I agree with Jordan and Emil. This preprocessor is too
yuk for a public header. I feel that the public header should be
readable code, a document that the user can refer to. This patch's macro
usage obfuscates the header's readability. (I point to xcb's public
headers as an example of well-readable, well-documented headers).

> > - with external definitions and scripts

Generating a few source files with scripts seems like the right approach
to me. The danger here is that it's very easy to overengineer generator
scripts and their input files. However, since you currently only want to
dynamically generate enum code, I think we can safely keep the scripts
and data dumb and simple.

> > What's the right tool for job?  Repetition might be ok if you only
> > need something in a couple places, but gets old fast if you have to
> > edit six places every time you want to add an item to a list.  XML and
> > scripts might be appropriate if you need to do something complicated,
> > something the preprocessor can't do.
> > I chose middle ground here, to get rid of repetition as simply as possible.
> > FWIW the macro list pattern has already been introduced to waffle.
> > See wgbm_platform.h.
> >
> > Is your objection purely for aesthetic reasons or is there some
> > technical drawback?
> > If aesthetics are important, would it make any difference if we move
> > the list macro out of the public header and into a private header?
> > Then we'd be repeating the list once, but subsequent uses would employ
> > the private macro. Though this would also deprive waffle users of the
> > chance to use the macro.

"Though this would also deprive waffle users of the chance to use the
macro." Oh no! I think we should *not* provide users any chance to use
these macros, If the header did contains these macros, then we should at
least make them *private* macros with a double-underscore prefix.
(Sigh... old friend C, why don't you have a proper module system?).

But, like I stated above, I want to avoid these macros altogether.

> >
> > "Yucky" is in the eye of the beholder.  (^:
> >

:) Several people have called my gl_basic_draw() macro in
tests/functional/gl_basic_test.c weird and ugly, but I'm very proud of
it :)  That macro transforms a regular C function into a python-esque
function having optional named parameters with default values!

> FWIW I also find it yucky - be that here or in gbm_platform.h. I
> withheld my objection in the latter as I felt that 1) it's an internal
> header and 2) I may have been bashing a bit too much on your
> contributions :-)
> 
> Although for a public header I would seriously object against this -
> ideally something like XML can be used, although if you (or others)
> feel like it's an overkill, I would be ok with moving it into internal
> header.

There's enough pushback on these macros from Jordan, Emil, and me, that
I think the best approach is to follow the steps of other projects, like
xcb and GL and piglit and libepoxy, and start generating waffle.h.

Since the only dynamically generated portion of waffle.h (for now, at
least) will be the enum definitions, there's no reason to use XML if you
feel it's overkill. (I'm also not opposed to XML, if you do want to go
that route).

My preference is to keep the generator scripts and their input dumb and
simple. Maybe we could add a json file somewhere that lists the enums
(and possibly their categories too).

    # file: src/waffle/waffle_enums.json
    {
        "waffle_error": [
            ["WAFFLE_NO_ERROR", "0x00"],
            ["WAFFLE_ERROR_FATAL", "0x01"],
            ...
        ],
        "waffle_enum": [
            ["WAFFLE_DONT_CARE", "-1", "generic"],
            ["WAFFLE_NONE", "0", "generic"],
            ["WAFFLE_PLATFORM", "0x0010", "waffle_init"],
            ["WAFFLE_PLATFORM_ANDROID", "0x0011", "waffle_init"],
            ["WAFFLE_PLATFORM_CGL", "0x0011", "waffle_init"],
        ...
        ]
    }

And stuff all of include/waffle/waffle.h into a big python file,
include/waffle/waffle_h_gen.py.

    #!/usr/bin/env python3
    # file: include/waffle/waffle_h_gen.py

    ...

    printf(textwrap.dedent("""\
        // Copyright 2012 Intel Corporation
        // Copyright 2015 Google
        //
        // All rights reserved.
        [...]
        enum waffle_error {"""))

    for (name, value) in enum_json["waffle_error"].items():
        printf("    {0} = {1},").format(name, value)

    print(textwrap.dedent("""\
        };

        struct waffle_error_info {
            enum waffle_error code;
            const char *message;
            size_t message_length;
        };

        enum waffle_error
        waffle_error_get_code(void);
        [...]
        """));

    [blah blah blah, more python]



If you wanted to go *really* simple, we could just put all the enums in
a flat text file and process it with sed, like so:

    # file: waffle_enums.txt
    waffle_error:WAFFLE_NO_ERROR:0x00
    waffle_error:WAFFLE_ERROR_FATAL:0x01
    [...]
    waffle_enum:WAFFLE_DONT_CARE:-1
    waffle_enum:WAFFLE_NONE:0
    waffle_enum:WAFFLE_PLATFORM:0x0010
    waffle_enum:WAFFLE_PLATFORM_ANDROID:0x0011
    waffle_enum:WAFFLE_PLATFORM_CGL:0x0012
    [...]


XML, JSON, or Unixy-style flat text file --- I don't really care, as
long the generator script isn't too complicated.


More information about the waffle mailing list