Drawing a blank with XS

I spent quite a lot of time trying to work out what this error message meant:

Error: Unterminated '#if/#ifdef/#ifndef' in Libpng.xs, line 1328

The first problem here is that line 1328 is the end of the file, so that wasn't a big help.

After spending a lot of time counting #if and #endif statements in the file over and over again, in the end I had the bright idea of looking at the actual XS output, and managed to find the problem. Apologies for quoting it in full here but I can't think of a good way to truncate it:

#if 0
#define XSubPPtmpAAAD 1


XS_EUPXS(XS_Image__PNG__Libpng_set_crc_action); /* prototype to pass -Wmissing-prototypes */Image__PNG__Libpng_set_crc_action)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "Png, crit_action, ancil_action");
    {
        Image__PNG__Libpng      Png;
        int     crit_action = (int)SvIV(ST(1))
;
        int     ancil_action = (int)SvIV(ST(2))
;

        if (SvROK(ST(0)) && sv_derived_from(ST(0), "Image::PNG::Libpng")) {

            IV tmp = SvIV((SV*)SvRV(ST(0)));
            Png = INT2PTR(Image__PNG__Libpng,tmp);
        }
        else
            Perl_croak_nocontext("%s: %s is not of type %s",
                        "Image::PNG::Libpng::set_crc_action",
                        "Png", "Image::PNG::Libpng")
;
#line 905 "Libpng.xs"
        png_set_crc_action (Png->png, crit_action, ancil_action);
#endif /* 0 */
#line 2836 "Libpng.c"
    }
    XSRETURN_EMPTY;
}

Can you work it out?

It turns out that XS processes

#if 0

void
perl_png_set_crc_action  (Png, crit_action, ancil_action);
    Image::PNG::Libpng Png;
    int crit_action;
    int ancil_action;
CODE:
    png_set_crc_action (Png->png, crit_action, ancil_action);

#endif /* 0 */

completely differently from

#if 0

void
perl_png_set_crc_action  (Png, crit_action, ancil_action);
    Image::PNG::Libpng Png;
    int crit_action;
    int ancil_action;
CODE:
    png_set_crc_action (Png->png, crit_action, ancil_action);
#endif /* 0 */

In the former case, the #endif goes after the function, and in the latter case it goes into the function body before the end of the function.

2 Comments

Python: Let's make whitespace characters syntactically signicifant.

Perl: Hold my beer and watch this!

Leave a comment

About Ben Bullock

user-pic Perl user since about 2006, I have also released some CPAN modules.