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.
Python: Let's make whitespace characters syntactically signicifant.
Perl: Hold my beer and watch this!
XS is its own weird little world, like C++ templates or quantum field theory or something like that.
Do you know what the syntax for comments in XS is?
# comment
Now the syntax for preprocessor conditionals in XS is
# (conditional)
where "conditional" is (if|endif|ifdef|line|include|something|or|another).
In the XS manual it actually tells you to put whitespace before your comments like this:
# comment