On Fri, Apr 04, 2025 at 12:23:55PM +0200, Simon Josefsson wrote:
> Eric Blake <ebl...@redhat.com> writes:
> 
> > I'm trying to run indent on the GNU M4 source code base before a
> > release (it looks like gnulib added the ability to run make indent
> > since the last time I made an m4 release).  But one change that indent
> > is insisting on is wrong:
> >
> > -extern void m4_error (int, int, const char *, ...)
> > -  ATTRIBUTE_COLD ATTRIBUTE_FORMAT ((__printf__, 3, 4));
> > -extern void m4_error_at_line (int, int, const char *, int, const char *, 
> > ...)
> > -  ATTRIBUTE_COLD ATTRIBUTE_FORMAT ((__printf__, 5, 6));
> > -extern _Noreturn void m4_failure (int, const char *, ...)
> > +extern void
> > +m4_error (int, int, const char *, ...)
> > +     ATTRIBUTE_COLD ATTRIBUTE_FORMAT ((__printf__, 3, 4));
> > +     extern void m4_error_at_line (int, int, const char *, int, const char 
> > *,
> > +                                   ...)
> > +     ATTRIBUTE_COLD ATTRIBUTE_FORMAT ((__printf__, 5, 6));
> > +     extern _Noreturn void m4_failure (int, const char *, ...)
> >
> > The old format may be awkward for starting the function name after the
> > return type, but even if I break that up, emacs still recommends:
> >
> > extern void
> > m4_error (int, int, const char *, ...)
> >   ATTRIBUTE_COLD ATTRIBUTE_FORMAT ((__printf__, 3, 4));
> >
> > And once indent gets messed up by the double attribute (both
> > ATTRIBUTE_COLD and ATTRIBUTE_FORMAT are macros that expand to
> > __attribute__ magic; the former without parameters), then the rest of
> > the file is messed up (as seen by the four-space indent before the
> > next extern function line).  Any ideas on how to tell indent about
> > ALL_CAPS macros that fit in attribute positions of declarations?
> 
> In GNU Libidn2's idn2.h I do it like this:
> 
> # if defined __GNUC__ && defined __GNUC_MINOR__
> #  define GCC_VERSION_AT_LEAST(major, minor) ((__GNUC__ > (major)) || 
> (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
> # else
> #  define GCC_VERSION_AT_LEAST(major, minor) 0
> # endif
> # if GCC_VERSION_AT_LEAST(2,96)
> #  define G_GNUC_IDN2_ATTRIBUTE_PURE __attribute__ ((pure))
> # else
> #  define G_GNUC_IDN2_ATTRIBUTE_PURE
> # endif
> 
>   extern _IDN2_API const char *idn2_check_version (const char *req_version)
>     G_GNUC_IDN2_ATTRIBUTE_PURE;

Figuring out how to write the __attribute__-hiding macros conditional
on compiler version wasn't the issue (the m4 definitions for
ATTRIBUTE_PURE come from gnulib, and are under a similar ladder of
#if); rather, it's that an all-caps macro that takes no arguments and
appears after the func(params) but before the trailing ; of an extern
function declaration confuse indent.

> 
> GNU Libtasn1 libtasn1.h has some similar usages too.
> 
> Not sure if this helps, but maybe this approach could be explored?
> 
> I suppose you are familiar with the hack to just disable indent for a
> small piece of code too:
> 
>   /* *INDENT-OFF* */
> 
> extern void
> m4_error (int, int, const char *, ...)
>   ATTRIBUTE_COLD ATTRIBUTE_FORMAT ((__printf__, 3, 4));
> 
>   /* *INDENT-ON* */

Yep, that's what I resorted to in the short term:
https://git.savannah.gnu.org/cgit/m4.git/diff/src/m4.h?h=branch-1.4

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org


Reply via email to