bug-gnulib
[Top][All Lists]
Advanced

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

proposal: lib/verify.h


From: Jim Meyering
Subject: proposal: lib/verify.h
Date: Wed, 29 Jun 2005 22:24:07 +0200

[to make a long story short, skip down to the `I propose...'
 part near the end. ]

Yesterday I did this in coreutils

        * src/pr.c (main, store_char): Use x2realloc on 1-byte base types,
        not x2nrealloc.  The former is a little more concise and readable.
        N.B. this sort of transformation is ok only when the base type is
        unlikely ever to change to a multibyte type.
        * src/du.c (show_date): Likewise.
        * src/date.c (show_date): Likewise.
        * src/od.c (dump_strings): Likewise.
        * src/sort.c (fillbuf): Likewise.

For example:

diff -p -u0 -r1.315 -r1.316 sort.c
--- sort.c      16 Jun 2005 21:33:43 -0000      1.315
+++ sort.c      28 Jun 2005 16:33:20 -0000      1.316
@@ -1062 +1062 @@ fillbuf (struct buffer *buf, FILE *fp, c
-      buf->buf = x2nrealloc (buf->buf, &buf->alloc, sizeof *(buf->buf));
+      buf->buf = x2realloc (buf->buf, &buf->alloc);

But then I realized that while the above changes made things a
little more concise and maybe even a little cleaner, they also
added a potential risk.

So I added an intermediate X2REALLOC macro, and made all of the
above use that instead of using x2realloc directly.

2005-06-29  Jim Meyering  <address@hidden>

        * xalloc.h (VERIFY_EXPR): Define.
        (X2REALLOC): New macro, to make using x2realloc a little safer.

Index: lib/xalloc.h
===================================================================
RCS file: /fetish/cu/lib/xalloc.h,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -p -u -r1.27 -r1.28
--- lib/xalloc.h        14 May 2005 07:58:07 -0000      1.27
+++ lib/xalloc.h        29 Jun 2005 16:33:17 -0000      1.28
@@ -56,6 +56,15 @@ void *x2nrealloc (void *p, size_t *pn, s
 void *xmemdup (void const *p, size_t s);
 char *xstrdup (char const *str);
 
+# define VERIFY_EXPR(assertion) \
+    (void)((struct {char a[(assertion) ? 1 : -1]; } *) 0)
+
+/* Using x2realloc (when appropriate) usually makes your code more
+   readable than using x2nrealloc, but it also makes it so your
+   code will malfunction if sizeof (*P) ever becomes 2 or greater.
+   So use this macro instead of using x2realloc directly.  */
+# define X2REALLOC(P, PN) (VERIFY_EXPR (sizeof(*P) == 1), x2realloc (P, PN))
+
 /* Return 1 if an array of N objects, each of size S, cannot exist due
    to size arithmetic overflow.  S must be positive and N must be
    nonnegative.  This is a macro, not an inline function, so that it

Before, this definition of VERIFY_EXPR was only in coreutils/src/system.h.
Now, a copy is in coreutils/lib/xalloc.h, too.  I like to avoid duplication.
Then there is a companion macro in coreutils/src/system.h, VERIFY:
(updated a couple of hours ago)

  #define GL_CONCAT...
  #define VERIFY(assertion) \
    struct GL_CONCAT (compile_time_assert_, __LINE__) \
      { char a[(assertion) ? 1 : -1]; }

that is similar to the `verify' macro used in these gnulib files:

  exclude.c
  mktime.c
  strtoimax.c
  utimecmp.c

Plus, I want to use it in argmatch:

Index: lib/argmatch.h
===================================================================
RCS file: /fetish/cu/lib/argmatch.h,v
retrieving revision 1.24
diff -u -p -u -0 -r1.24 argmatch.h
--- lib/argmatch.h      14 May 2005 07:58:06 -0000      1.24
+++ lib/argmatch.h      29 Jun 2005 16:52:19 -0000
@@ -38,5 +38,2 @@
-# define ARGMATCH_VERIFY(Arglist, Vallist)                               \
-  struct argmatch_verify                                                 \
-  {                                                                      \
-    char argmatch_verify[ARGMATCH_CONSTRAINT(Arglist, Vallist) ? 1 : -1]; \
-  }
+# define ARGMATCH_VERIFY(Arglist, Vallist) \
+    VERIFY (ARGMATCH_CONSTRAINT (Arglist, Vallist))

so that I can use ARGMATCH_VERIFY twice in cp.c's
global scope (currently I cannot) and 6 times in ls.c's
BTW, these new uses of ARGMATCH_VERIFY exposed two
arrays that were too long by a single `0' entry.
But both were harmless.

================================
I propose to add a new file, verify.h, and to include
in it these definitions:

#define GL_CONCAT0(x, y) x##y
#define GL_CONCAT(x, y) GL_CONCAT0 (x, y)
/* Verify a requirement at compile-time (unlike assert, which is runtime).  */
#define VERIFY(assertion) \
  struct GL_CONCAT (compile_time_assert_, __LINE__) \
    { char a[(assertion) ? 1 : -1]; }

/* Like the above, but use an expression rather than a struct declaration.
   This macro may be used in some contexts where the other may not.  */
#define VERIFY_EXPR(assertion) \
  (void)((struct {char a[(assertion) ? 1 : -1]; } *) 0)

Then, the following files (with the possible exception of mktime.c
due to its glibc ties) would include "verify.h":

  exclude.c
  mktime.c
  strtoimax.c
  utimecmp.c

It'd be nice to make xalloc.h and argmatch.h include it, too, but
duplicating one primary definition in each is probably better than
adding the dependency -- at least for xalloc.h.

Opinions welcome.




reply via email to

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