Question

I'm in the process of porting some code from the GIMP source code base into a program I am writing. Part of the code (/gimp-2.8.10//modules/display-filter-color-blind.c) references a macro called GIMP_CAIRO_ARGB32_SET_PIXEL (gimp-2.8.10//libgimpcolor/gimpcairocolor.h). Within that macro there is something called G_STMT_START/G_STMT_END. My compiler (Mac OSX via Xcode with the default compiler) is complaining with the error "Use of undeclared identifier 'G_STMT_START'" I know it is not a scoping issue with where I put the macros (in a header file called globals.h that I include in my .h) because the compiler is not complaining about the GIMP_CAIRO_ARGB32_SET_PIXEL define.

Does anyone know whats going on here? I've attempted to grep through all instances of G_STMT_START in the GIMP source but have not found anything that seems to define G_STMT_START/G_STMT_END. I also found sort of an explanation in the GIMP toolkit documentation, but it's far from helpful (for me at least).

This is the full macro that I am trying to use:

/**
 * GIMP_CAIRO_ARGB32_SET_PIXEL:
 * @d: pointer to the destination buffer
 * @r: red component, not pre-multiplied
 * @g: green component, not pre-multiplied
 * @b: blue component, not pre-multiplied
 * @a: alpha component
 *
 * Sets a single pixel in an Cairo image surface in %CAIRO_FORMAT_ARGB32.
 *
 * Since: GIMP 2.6
 **/
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define GIMP_CAIRO_ARGB32_SET_PIXEL(d, r, g, b, a) \
  G_STMT_START {                                   \
    const guint tr = (a) * (r) + 0x80;             \
    const guint tg = (a) * (g) + 0x80;             \
    const guint tb = (a) * (b) + 0x80;             \
    (d)[0] = (((tb) >> 8) + (tb)) >> 8;            \
    (d)[1] = (((tg) >> 8) + (tg)) >> 8;            \
    (d)[2] = (((tr) >> 8) + (tr)) >> 8;            \
    (d)[3] = (a);                                  \
  } G_STMT_END
#else
#define GIMP_CAIRO_ARGB32_SET_PIXEL(d, r, g, b, a) \
  G_STMT_START {                                   \
    const guint tr = (a) * (r) + 0x80;             \
    const guint tg = (a) * (g) + 0x80;             \
    const guint tb = (a) * (b) + 0x80;             \
    (d)[0] = (a);                                  \
    (d)[1] = (((tr) >> 8) + (tr)) >> 8;            \
    (d)[2] = (((tg) >> 8) + (tg)) >> 8;            \
    (d)[3] = (((tb) >> 8) + (tb)) >> 8;            \
  } G_STMT_END
#endif

Thanks for any help with this!

Was it helpful?

Solution

I had no idea what this might be either (although now that I know, I'm telling myself that I could probably have guessed), but all it took to find out was entering G_STMT_START into Google and clicking on the first result.

That page, documentation from the Glib manual, reveals that it is a macro designed to be used within multi-statement macros.

G_STMT_START

#define     G_STMT_START

Used within multi-statement macros so that they can be used in places where only one statement is expected by the compiler.

G_STMT_END

#define     G_STMT_END

Used within multi-statement macros so that they can be used in places where only one statement is expected by the compiler.

Later on in the search results, you'll get one or more copies of the gmacros.h header file, where these macros are actually defined:

/* Provide simple macro statement wrappers (adapted from Perl):
 *  G_STMT_START { statements; } G_STMT_END;
 *  can be used as a single statement, as in
 *  if (x) G_STMT_START { ... } G_STMT_END; else ...
 *
 *  For gcc we will wrap the statements within `({' and `})' braces.
 *  For SunOS they will be wrapped within `if (1)' and `else (void) 0',
 *  and otherwise within `do' and `while (0)'.
 */
#if !(defined (G_STMT_START) && defined (G_STMT_END))
#  if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
#    define G_STMT_START    (void) __extension__ (
#    define G_STMT_END      )
#  else
#    if (defined (sun) || defined (__sun__))
#      define G_STMT_START  if (1)
#      define G_STMT_END    else (void)0
#    else
#      define G_STMT_START  do
#      define G_STMT_END    while (0)
#    endif
#  endif
#endif

From that, it becomes pretty clear that these macros are just implementing the standard idiom, except on GCC where they use the extension intended for precisely this purpose.

I'd figure that there will be other parts of the GIMP code that will depend on the Glib headers, so you'll probably want to include them if you're using its code. But if not, there's enough information here to implement the relevant portions of code yourself.

OTHER TIPS

G_STMT_START and G_STMT_END are macros in the Gnome Glib library that gimp depends on.

They are defined in gmacros.h.

Currently, the documentation of GTK 4 - GLib 2.0 no longer includes miscellaneous macros like G_STMT_START, G_STMT_END, etc. If you look through old documentation from other sources like geany or the web archive, you can see that they are defined as

#define G_STMT_START  do
#define G_STMT_END    while (0)

Actually, in <glib/gmacros.h> (for GLib 2.0), the real definitions are:

#if !(defined (G_STMT_START) && defined (G_STMT_END))
#define G_STMT_START  do
#if defined (_MSC_VER) && (_MSC_VER >= 1500)
#define G_STMT_END \
    __pragma(warning(push)) \
    __pragma(warning(disable:4127)) \
    while(0) \
    __pragma(warning(pop))
#else
#define G_STMT_END    while (0)
#endif
#endif

It just wraps a do ... while(0) block. The effect of this macro pair is well introduced by Cody Gray's answer - the standard idiom.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top