bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug-gnulib] Re: automatic prototypes


From: Jim Meyering
Subject: [bug-gnulib] Re: automatic prototypes
Date: Thu, 03 Feb 2005 09:32:04 +0100

Paul Eggert <address@hidden> wrote:
> Jim Meyering <address@hidden> writes:
>
>> Here's the change I'm considering for memrchr.m4.
>
> The technique used for other glibc extensions (e.g., getcwd, getopt,)
> lchown, mbswidth, memmem) is to have a .h file for that extension.
> So we could have a file "memrchr.h" for memrchr.
>
> However, that leads to a proliferation of little .h files.

Right.  I'd rather avoid that, if at all possible.

> Perhaps it
> would be simpler and easier to have a file "string-gnu.h" that
> contains all the GNU extensions to string.h, and consolidate
> memrchr.h, memmem.h, into string-gnu.h.  Similarly for unistd-gnu.h
> and getcwd/getopt, etc.

I have mixed feelings about this idea.
On one hand, it documents in the code the dependency on a nonstandard
interface.  But it also means more hard-to-check work for the developer:
remembering to include that extra file, in case the code is built on
a non-GNU system.  Sure, if they remember to include string-gnu.h from
the start there's no problem, but if they do `man memrchr' and see that
<string.h> is required, they might not add string-gnu.h until someone
reports the problem when building on a non-GNU system.

> string-gnu.h could include string.h, so there'd be no need for a program
> to include both files.

That sounds good, but it would be better not to have to include
any extra file at all.  For functions involving only types like
struct stat*, char*, uid_t, gid_t, pid_t, size_t, ssize_t, etc.,
that shouldn't be hard.

For struct stat*, all you need is a forward declaration.  For the
others we'd need a macro to determine the corresponding type.
But FILE* might be hard.

I'm thinking of a macro that'd iterate over the potential
types until it finds one that matches the desired typedef.
So if we wanted to do the typedefs all at once, ...

  for typedef in uid_t gid_t pid_t size_t ssize_t; do
    for t in char 'short int' int 'long int' 'long long int'; do
      for type in $t "unsigned $t" "signed $t"; do
        # see if $typedef and $type have same size and signedness
      done
    done
  done

Then, for each $typedef, it'd try to compile a little program like this,
until it finds a `$type' that works:

  #define GL_$typedef $type

  /* Verify a requirement at compile-time (unlike assert, which is runtime).  */
  #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }

  /* The extra casts work around common compiler bugs.  */
  #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))

  #include <stddef.h>

  verify (${typedef}_size, sizeof (size_t) == sizeof (GL_$typedef));
  verify (${typedef}_sign, TYPE_SIGNED (size_t) == TYPE_SIGNED (GL_$typedef));

The net result would be, e.g. for memrchr, a definition
of GL_size_t in config.h and a prototype of memrchr using that type
at the bottom of config.h.

  #define GL_size_t unsigned int
  ...
  void *memrchr(const void *s, int c, GL_size_t n);

Of course, this is all predicated upon it being ok to
put non-cpp-directives (the prototypes) at the end of config.h.

Does anyone see a problem?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]