Skip to content

Conversation

@alejandro-colomar
Copy link
Collaborator

@alejandro-colomar alejandro-colomar commented Jun 4, 2025

Simplify and centralize the implementation of function variants that exit on error.


Revisions:

v1b
  • Rebase
$ git rd 
1:  db513577 = 1:  a0d169d5 lib/: X(): Add macro to exit() on error
2:  2d05cfcc = 2:  3cafcd16 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  f9ccb172 = 3:  f95e2ea3 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  727b967a = 4:  b4f10a23 lib/string/sprintf/: xaprintf(): Reimplement in terms of X()
5:  d99d82da = 5:  ec706b48 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  80aec6fb = 6:  56aac974 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  4dc8c9e6 ! 7:  98d83757 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/getdef.c
      #include "string/strcmp/streq.h"
      #include "string/strcmp/strprefix.h"
     
    - ## lib/gshadow.c ##
    -@@
    - 
    - #include "alloc/malloc.h"
    - #include "alloc/realloc.h"
    --#include "alloc/x/xmalloc.h"
    - #include "defines.h"
    - #include "prototypes.h"
    - #include "string/strchr/strchrcnt.h"
    -
      ## lib/idmapping.c ##
     @@
      #endif
    @@ lib/list.c
      #include "string/strcmp/streq.h"
     -#include "string/strdup/xstrdup.h"
     +#include "string/strdup/strdup.h"
    + #include "string/strtok/strsep2ls.h"
      
      
    - /*
     
      ## lib/mail.c ##
     @@
    @@ src/newusers.c
     -#include "string/strdup/xstrdup.h"
     +#include "string/strdup/strdup.h"
      #include "string/strtok/stpsep.h"
    - 
    + #include "string/strtok/strsep2arr.h"
      
     
      ## src/passwd.c ##
v2
  • Do likewise with the newly added xastrsep2ls().
$ git range-diff shadow/master gh/x x 
1:  a0d169d5 = 1:  a0d169d5 lib/: X(): Add macro to exit() on error
2:  3cafcd16 = 2:  3cafcd16 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  f95e2ea3 = 3:  f95e2ea3 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  b4f10a23 = 4:  b4f10a23 lib/string/sprintf/: xaprintf(): Reimplement in terms of X()
5:  ec706b48 = 5:  ec706b48 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  56aac974 = 6:  56aac974 lib/string/strdup/xstrndup.h: Add STRNDUP()
-:  -------- > 7:  1775ed65 lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
7:  98d83757 ! 8:  14d0c3e9 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/Makefile.am: libshadow_la_SOURCES = \
        string/strftime.c \
        string/strftime.h \
        string/strspn/stpspn.c \
    +@@ lib/Makefile.am: libshadow_la_SOURCES = \
    +   string/strtok/strsep2arr.h \
    +   string/strtok/strsep2ls.c \
    +   string/strtok/strsep2ls.h \
    +-  string/strtok/xastrsep2ls.c \
    +-  string/strtok/xastrsep2ls.h \
    +   strtoday.c \
    +   sub.c \
    +   subordinateio.h \
     
      ## lib/alloc/calloc.h ##
     @@
    @@ lib/getdef.c
      #include "string/strcmp/streq.h"
      #include "string/strcmp/strprefix.h"
     
    + ## lib/gshadow.c ##
    +@@
    + #include "defines.h"
    + #include "prototypes.h"
    + #include "string/strcmp/streq.h"
    ++#include "string/strtok/astrsep2ls.h"
    + #include "string/strtok/stpsep.h"
    + #include "string/strtok/strsep2arr.h"
    +-#include "string/strtok/xastrsep2ls.h"
    + 
    + 
    + static /*@null@*/FILE *shadow;
    +
      ## lib/idmapping.c ##
     @@
      #endif
    @@ lib/string/strdup/xstrdup.c (deleted)
     -
     -#include "string/strdup/xstrdup.h"
     
    + ## lib/string/strtok/astrsep2ls.h ##
    +@@
    +-// SPDX-FileCopyrightText: 2024, Alejandro Colomar <[email protected]>
    ++// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar <[email protected]>
    + // SPDX-License-Identifier: BSD-3-Clause
    + 
    + 
    +@@
    + #include "attr.h"
    + #include "string/strchr/strchrscnt.h"
    + #include "string/strtok/strsep2ls.h"
    ++#include "x.h"
    ++
    ++
    ++#define xastrsep2ls(s, delim, np)  X(astrsep2ls(s, delim, np))
    + 
    + 
    + ATTR_ACCESS(read_write, 1) ATTR_ACCESS(write_only, 3)
    +
    + ## lib/string/strtok/xastrsep2ls.c (deleted) ##
    +@@
    +-// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar <[email protected]>
    +-// SPDX-License-Identifier: BSD-3-Clause
    +-
    +-
    +-#include <config.h>
    +-
    +-#include "string/strtok/xastrsep2ls.h"
    +
    + ## lib/string/strtok/xastrsep2ls.h (deleted) ##
    +@@
    +-// SPDX-FileCopyrightText: 2024-2025, Alejandro Colomar <[email protected]>
    +-// SPDX-License-Identifier: BSD-3-Clause
    +-
    +-
    +-#ifndef SHADOW_INCLUDE_LIB_STRING_STRTOK_XASTRSEP2LS_H_
    +-#define SHADOW_INCLUDE_LIB_STRING_STRTOK_XASTRSEP2LS_H_
    +-
    +-
    +-#include <config.h>
    +-
    +-#include "string/strtok/astrsep2ls.h"
    +-#include "x.h"
    +-
    +-
    +-#define xastrsep2ls(s, delim, np)  X(astrsep2ls(s, delim, np))
    +-
    +-
    +-#endif  // include guard
    +
      ## lib/utmp.c ##
     @@
      #include <string.h>
v2b
  • Rebase
$ git rd
1:  a0d169d5 = 1:  2457b0b3 lib/: X(): Add macro to exit() on error
2:  3cafcd16 = 2:  caa136e7 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  f95e2ea3 = 3:  ea734fb4 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  b4f10a23 = 4:  a90b89fb lib/string/sprintf/: xaprintf(): Reimplement in terms of X()
5:  ec706b48 = 5:  c06652d3 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  56aac974 = 6:  a62faca1 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  1775ed65 = 7:  f57f94de lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  14d0c3e9 = 8:  2ac1426e lib/, src/, tests/: Move x*() definitions to non-x* header files
v3
  • Rebase
  • #include "config.h" with quotes.
$ git rd
1:  2457b0b3 ! 1:  58f452c9 lib/: X(): Add macro to exit() on error
    @@ lib/x.c (new)
     +// SPDX-License-Identifier: BSD-3-Clause
     +
     +
    -+#include <config.h>
    ++#include "config.h"
     +
     +#include "x.h"
     +
    @@ lib/x.h (new)
     +#define SHADOW_INCLUDE_LIB_X_H_
     +
     +
    -+#include <config.h>
    ++#include "config.h"
     +
     +#include <errno.h>
     +#include <stddef.h>
2:  caa136e7 = 2:  7cc506e5 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  ea734fb4 = 3:  8449d6e1 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  a90b89fb ! 4:  3ab19b61 lib/string/sprintf/: xaprintf(): Reimplement in terms of X()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/sprintf/: xaprintf(): Reimplement in terms of X()
    +    lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ tests/unit/Makefile.am: test_typetraits_LDADD = \
     +    ../../lib/shadowlog.c \
          ../../lib/string/sprintf/aprintf.c \
          ../../lib/string/sprintf/xaprintf.c \
    +     ../../lib/string/strcmp/streq.c \
     +    ../../lib/x.c \
          test_xaprintf.c \
          $(NULL)
5:  c06652d3 = 5:  40be2724 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  a62faca1 = 6:  e60e2419 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  f57f94de = 7:  1b841cad lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  2ac1426e ! 8:  0f51a85b lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ tests/unit/Makefile.am: test_typetraits_LDADD = \
          ../../lib/shadowlog.c \
          ../../lib/string/sprintf/aprintf.c \
     -    ../../lib/string/sprintf/xaprintf.c \
    +     ../../lib/string/strcmp/streq.c \
          ../../lib/x.c \
          test_xaprintf.c \
    -     $(NULL)
     
      ## tests/unit/test_xaprintf.c ##
     @@
    - #include <stdint.h>  // Required by <cmocka.h>
    - #include <cmocka.h>
    + // SPDX-License-Identifier: BSD-3-Clause
    + 
      
     -#include "string/sprintf/xaprintf.h"
     +#include "string/sprintf/aprintf.h"
      
    - 
    - #define smock()               _Generic(mock(), uintmax_t: (intmax_t) mock())
    + #include <setjmp.h>
    + #include <stdarg.h>
v3b
  • Rebase
$ git rd 
1:  58f452c9 = 1:  f4f31c7a lib/: X(): Add macro to exit() on error
2:  7cc506e5 ! 2:  5a4d9f8a lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
    @@ lib/string/strdup/xstrdup.c
      // SPDX-License-Identifier: BSD-3-Clause
      
     @@
    - #include <config.h>
    + #include "config.h"
      
      #include "string/strdup/xstrdup.h"
     -
3:  8449d6e1 ! 3:  33a8ff5a lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
    @@ lib/alloc/x/xcalloc.c
      // SPDX-License-Identifier: BSD-3-Clause
      
     @@
    - #include <config.h>
    + #include "config.h"
      
      #include "alloc/x/xcalloc.h"
     -
    @@ lib/alloc/x/xcalloc.h
      
     @@
      
    - #include <config.h>
    + #include "config.h"
      
     -#include <stddef.h>
     -#include <stdlib.h>
    @@ lib/alloc/x/xmalloc.c
      // SPDX-License-Identifier: BSD-3-Clause
      
     @@
    - #include <config.h>
    + #include "config.h"
      
      #include "alloc/x/xmalloc.h"
     -
    @@ lib/alloc/x/xmalloc.h
      
     @@
      
    - #include <config.h>
    + #include "config.h"
      
     -#include <stddef.h>
     -
    @@ lib/alloc/x/xrealloc.c
      // SPDX-License-Identifier: BSD-3-Clause
      
     @@
    - #include <config.h>
    + #include "config.h"
      
      #include "alloc/x/xrealloc.h"
     -
    @@ lib/alloc/x/xrealloc.h
     +#define SHADOW_INCLUDE_LIB_ALLOC_X_XREALLOC_H_
      
      
    - #include <config.h>
    + #include "config.h"
      
     -#include <assert.h>
     -#include <errno.h>
4:  3ab19b61 ! 4:  d51e146c lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
    @@ Commit message
     
      ## lib/string/sprintf/xaprintf.c ##
     @@
    - #include <config.h>
    + #include "config.h"
      
      #include "string/sprintf/xaprintf.h"
     -
    @@ lib/string/sprintf/xaprintf.c
      ## lib/string/sprintf/xaprintf.h ##
     @@
      
    - #include <config.h>
    + #include "config.h"
      
     -#include <stdarg.h>
     -#include <stddef.h>
5:  40be2724 = 5:  a8221c4f lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  e60e2419 = 6:  afcb8751 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  1b841cad ! 7:  9e550868 lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
    @@ lib/string/strtok/xastrsep2ls.c
      // SPDX-License-Identifier: BSD-3-Clause
      
      
    - #include <config.h>
    + #include "config.h"
      
      #include "string/strtok/xastrsep2ls.h"
     -
    @@ lib/string/strtok/xastrsep2ls.h
      
     @@
      
    - #include <config.h>
    + #include "config.h"
      
     -#include <errno.h>
     -#include <stddef.h>
8:  0f51a85b ! 8:  4933b19b lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/alloc/realloc.h
      
      
     @@
    - #include <config.h>
    + #include "config.h"
      
      #include <stdlib.h>
     +#include "x.h"
    @@ lib/alloc/x/xcalloc.h (deleted)
     -#define SHADOW_INCLUDE_LIB_ALLOC_X_XCALLOC_H_
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "alloc/calloc.h"
     -#include "x.h"
    @@ lib/alloc/x/xmalloc.c (deleted)
     -// SPDX-License-Identifier: BSD-3-Clause
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "alloc/x/xmalloc.h"
     
    @@ lib/alloc/x/xmalloc.h (deleted)
     -#define SHADOW_INCLUDE_LIB_ALLOC_X_XMALLOC_H_
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "alloc/malloc.h"
     -#include "x.h"
    @@ lib/alloc/x/xrealloc.c (deleted)
     -// SPDX-License-Identifier: BSD-3-Clause
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "alloc/x/xrealloc.h"
     
    @@ lib/alloc/x/xrealloc.h (deleted)
     -#define SHADOW_INCLUDE_LIB_ALLOC_X_XREALLOC_H_
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "alloc/realloc.h"
     -#include "x.h"
    @@ lib/string/sprintf/xaprintf.c (deleted)
     -// SPDX-License-Identifier: BSD-3-Clause
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "string/sprintf/xaprintf.h"
     
    @@ lib/string/sprintf/xaprintf.h (deleted)
     -#define SHADOW_INCLUDE_LIB_STRING_SPRINTF_XASPRINTF_H_
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "string/sprintf/aprintf.h"
     -#include "x.h"
    @@ lib/string/sprintf/xaprintf.h (deleted)
      ## lib/alloc/x/xcalloc.c => lib/string/strdup/strdup.c ##
     @@
      
    - #include <config.h>
    + #include "config.h"
      
     -#include "alloc/x/xcalloc.h"
     +#include "string/strdup/strdup.h"
    @@ lib/string/strdup/xstrdup.h => lib/string/strdup/strdup.h
     +#define SHADOW_INCLUDE_LIB_STRING_STRDUP_STRDUP_H_
      
      
    - #include <config.h>
    + #include "config.h"
     
      ## lib/string/strdup/xstrndup.c => lib/string/strdup/strndup.c ##
     @@
      
    - #include <config.h>
    + #include "config.h"
      
     -#include "string/strdup/xstrndup.h"
     +#include "string/strdup/strndup.h"
    @@ lib/string/strdup/xstrndup.h => lib/string/strdup/strndup.h
     +#define SHADOW_INCLUDE_LIB_STRING_STRDUP_STRNDUP_H_
      
      
    - #include <config.h>
    + #include "config.h"
     
      ## lib/string/strdup/xstrdup.c (deleted) ##
     @@
    @@ lib/string/strdup/xstrdup.c (deleted)
     -// SPDX-License-Identifier: BSD-3-Clause
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "string/strdup/xstrdup.h"
     
    @@ lib/string/strtok/xastrsep2ls.c (deleted)
     -// SPDX-License-Identifier: BSD-3-Clause
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "string/strtok/xastrsep2ls.h"
     
    @@ lib/string/strtok/xastrsep2ls.h (deleted)
     -#define SHADOW_INCLUDE_LIB_STRING_STRTOK_XASTRSEP2LS_H_
     -
     -
    --#include <config.h>
    +-#include "config.h"
     -
     -#include "string/strtok/astrsep2ls.h"
     -#include "x.h"
    @@ lib/utmp.c
     +#include "alloc/calloc.h"
     +#include "alloc/malloc.h"
      #include "sizeof.h"
    + #include "string/strchr/strnul.h"
      #include "string/strcmp/streq.h"
      #include "string/strcmp/strprefix.h"
      #include "string/strcpy/strncpy.h"
v3c
  • Rebase
$ git rd 
1:  f4f31c7a = 1:  80241725 lib/: X(): Add macro to exit() on error
2:  5a4d9f8a = 2:  1b4025fc lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  33a8ff5a = 3:  f4be3264 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  d51e146c = 4:  e4b89e2b lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
5:  a8221c4f = 5:  0306fdb3 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  afcb8751 = 6:  498fcc09 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  9e550868 = 7:  979efa41 lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  4933b19b ! 8:  b3d319c5 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/utmp.c
     -#include "alloc/x/xmalloc.h"
     +#include "alloc/calloc.h"
     +#include "alloc/malloc.h"
    + #include "attr.h"
      #include "sizeof.h"
      #include "string/strchr/strnul.h"
    - #include "string/strcmp/streq.h"
    +@@
      #include "string/strcmp/strprefix.h"
      #include "string/strcpy/strncpy.h"
      #include "string/strcpy/strtcpy.h"
    @@ src/chage.c
     
      ## src/chfn.c ##
     @@
    - #include "string/sprintf/snprintf.h"
    + #include "string/sprintf/stpeprintf.h"
      #include "string/strcmp/streq.h"
      #include "string/strcpy/strtcpy.h"
     -#include "string/strdup/xstrdup.h"
     +#include "string/strdup/strdup.h"
    - #include "string/strtok/stpsep.h"
      
      
    + /*
     
      ## src/chsh.c ##
     @@
v3d
  • Rebase
$ git rd 
1:  80241725 = 1:  bbca7a18 lib/: X(): Add macro to exit() on error
2:  1b4025fc = 2:  ba91ca84 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  f4be3264 = 3:  76938f4b lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  e4b89e2b = 4:  aef9a97d lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
5:  0306fdb3 = 5:  10d343e3 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  498fcc09 = 6:  150c702c lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  979efa41 = 7:  a732517d lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  b3d319c5 = 8:  f54ffd9e lib/, src/, tests/: Move x*() definitions to non-x* header files
v3e
  • Rebase
$ git rd 
1:  bbca7a18 = 1:  0cf34075 lib/: X(): Add macro to exit() on error
2:  ba91ca84 = 2:  2cc55159 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  76938f4b = 3:  e6c57806 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  aef9a97d = 4:  a840221b lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
5:  10d343e3 = 5:  fd38efd7 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  150c702c = 6:  6151b57a lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  a732517d = 7:  35613d36 lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  f54ffd9e ! 8:  8add3f15 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/getdef.c
      #include "string/strcmp/streq.h"
      #include "string/strcmp/strprefix.h"
     
    - ## lib/gshadow.c ##
    -@@
    - #include "defines.h"
    - #include "prototypes.h"
    - #include "string/strcmp/streq.h"
    -+#include "string/strtok/astrsep2ls.h"
    - #include "string/strtok/stpsep.h"
    - #include "string/strtok/strsep2arr.h"
    --#include "string/strtok/xastrsep2ls.h"
    - 
    - 
    - static /*@null@*/FILE *shadow;
    -
      ## lib/idmapping.c ##
     @@
      #endif
    @@ lib/obscure.c
     
      ## lib/prefix_flag.c ##
     @@
    - #endif                            /* ENABLE_SUBIDS */
      #include "getdef.h"
    + #include "shadow/gshadow/gshadow.h"
      #include "shadowlog.h"
     -#include "string/sprintf/xaprintf.h"
     +#include "string/sprintf/aprintf.h"
    @@ lib/setupenv.c
      #include "string/strtok/stpsep.h"
      
     
    + ## lib/shadow/gshadow/sgetsgent.c ##
    +@@
    + 
    + #include "shadow/gshadow/sgrp.h"
    + #include "string/strcmp/streq.h"
    ++#include "string/strtok/astrsep2ls.h"
    + #include "string/strtok/stpsep.h"
    + #include "string/strtok/strsep2arr.h"
    +-#include "string/strtok/xastrsep2ls.h"
    + 
    + 
    + #if defined(SHADOWGRP) && !__has_include(<gshadow.h>)
    +
      ## lib/string/sprintf/aprintf.h ##
     @@
      #include <stdlib.h>
    @@ src/groupmems.c
      #include "groupio.h"
      #include "prototypes.h"
     @@
    - #endif
    + #include "shadow/gshadow/sgrp.h"
      #include "shadowlog.h"
      #include "string/strcmp/streq.h"
     -#include "string/strdup/xstrdup.h"
    @@ src/useradd.c
     
      ## src/userdel.c ##
     @@
    - #endif                            /* ENABLE_SUBIDS */
    + #include "shadow/gshadow/sgrp.h"
      #include "shadowlog.h"
      #include "string/sprintf/aprintf.h"
     -#include "string/sprintf/xaprintf.h"
v3f
  • Rebase
$ git range-diff 0cf34075add8^..gh/x shadow/master..x 
1:  0cf34075 = 1:  7f9d5368 lib/: X(): Add macro to exit() on error
2:  2cc55159 = 2:  f8aa47ee lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  e6c57806 = 3:  35f5c0f9 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  a840221b = 4:  1423cb69 lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
5:  fd38efd7 = 5:  1d1e38c9 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  6151b57a = 6:  01382e12 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  35613d36 = 7:  a224ff2c lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  8add3f15 = 8:  93d59cac lib/, src/, tests/: Move x*() definitions to non-x* header files
v4
  • Prevent double expansion of macro argument.
$ git range-diff shadow/master gh/x x 
1:  7f9d5368 ! 1:  49d1efe1 lib/: X(): Add macro to exit() on error
    @@ lib/x.c (new)
     +#include "x.h"
     +
     +
    -+extern inline void *x_(void *p);
    ++extern inline void x_(void *p);
     
      ## lib/x.h (new) ##
     @@
    @@ lib/x.h (new)
     +#include "shadowlog.h"
     +
     +
    -+#define X(p)  ((typeof(p)) x_(p))
    ++#define X(p)                                                          \
    ++({                                                                    \
    ++  __auto_type  p_ = p;                                          \
    ++                                                                      \
    ++  x_(p_);                                                       \
    ++  p_;                                                           \
    ++})
     +
     +
    -+inline void *x_(void *p);
    ++inline void x_(void *p);
     +
     +
    -+inline void *
    ++inline void
     +x_(void *p)
     +{
     +  if (p == NULL) {
    @@ lib/x.h (new)
     +                  log_get_progname(), strerror(errno));
     +          exit(13);
     +  }
    -+
    -+  return p;
     +}
     +
     +
2:  f8aa47ee = 2:  3793edff lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  35f5c0f9 = 3:  f73583cc lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  1423cb69 = 4:  85a0687a lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
5:  1d1e38c9 = 5:  32d00ccf lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  01382e12 = 6:  e5dbb53a lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  a224ff2c = 7:  202994a3 lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  93d59cac = 8:  f8a1a6d9 lib/, src/, tests/: Move x*() definitions to non-x* header files
v4b
  • Rename helper function.
$ git range-diff shadow/master gh/x x 
1:  49d1efe1 ! 1:  abd9bf9b lib/: X(): Add macro to exit() on error
    @@ lib/x.c (new)
     +#include "x.h"
     +
     +
    -+extern inline void x_(void *p);
    ++extern inline void exit_if_null(void *p);
     
      ## lib/x.h (new) ##
     @@
    @@ lib/x.h (new)
     +({                                                                    \
     +  __auto_type  p_ = p;                                          \
     +                                                                      \
    -+  x_(p_);                                                       \
    ++  exit_if_null(p_);                                             \
     +  p_;                                                           \
     +})
     +
     +
    -+inline void x_(void *p);
    ++inline void exit_if_null(void *p);
     +
     +
     +inline void
    -+x_(void *p)
    ++exit_if_null(void *p)
     +{
     +  if (p == NULL) {
     +          fprintf(log_get_logfd(), "%s: %s\n",
2:  3793edff = 2:  8d2909ea lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
3:  f73583cc = 3:  2e1a86c7 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
4:  85a0687a = 4:  e4194552 lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
5:  32d00ccf = 5:  651a7831 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
6:  e5dbb53a = 6:  8057a211 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  202994a3 = 7:  46518c4d lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
8:  f8a1a6d9 = 8:  3fb734f1 lib/, src/, tests/: Move x*() definitions to non-x* header files
v5
$ git range-diff shadow/master gh/x x 
1:  abd9bf9b ! 1:  b6189fd1 lib/: X(): Add macro to exit() on error
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/: X(): Add macro to exit() on error
    +    lib/: x(): Add macro to exit() on error
     
         Writing an x*() variant of several functions is unnecessary.  It's
    -    simpler to write a generic X() macro that can be chained with any other
    +    simpler to write a generic x() macro that can be chained with any other
         calls.
     
         For example:
     
    -            -  X(malloc(...)) instead of xmalloc(...);
    -            -  X(strdup(...)) instead of xstrdup(...);
    +            -  x(malloc(...)) instead of xmalloc(...);
    +            -  x(strdup(...)) instead of xstrdup(...);
     
         If an error is detected, log an error, and exit(13).  About why 13, I
         don't really know.  It's just what was used previously in xmalloc().
    @@ lib/x.h (new)
     +#include "shadowlog.h"
     +
     +
    -+#define X(p)                                                          \
    ++#define x(p)                                                          \
     +({                                                                    \
     +  __auto_type  p_ = p;                                          \
     +                                                                      \
2:  8d2909ea ! 2:  bdcc2abe lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of X()
    +    lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of x()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/string/strdup/xstrdup.h
     -{
     -  return strcpy(XMALLOC(strlen(str) + 1, char), str);
     -}
    -+#define xstrdup(s)  X(strdup(s))
    ++#define xstrdup(s)  x(strdup(s))
      
      
      #endif  // include guard
3:  2e1a86c7 ! 3:  9ca44660 lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/alloc/x/: X*ALLOC(): Reimplement in terms of X()
    +    lib/alloc/x/: X*ALLOC(): Reimplement in terms of x()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/alloc/x/xcalloc.h
     -ATTR_ALLOC_SIZE(1, 2)
     -ATTR_MALLOC(free)
     -void *xcalloc(size_t nmemb, size_t size);
    -+#define XCALLOC(n, type)  X(CALLOC(n, type))
    ++#define XCALLOC(n, type)  x(CALLOC(n, type))
      
      
      #endif  // include guard
    @@ lib/alloc/x/xmalloc.h
     -{
     -  return xreallocarray(NULL, nmemb, size);
     -}
    -+#define XMALLOC(n, type)  X(MALLOC(n, type))
    ++#define XMALLOC(n, type)  x(MALLOC(n, type))
      
      
      #endif  // include guard
    @@ lib/alloc/x/xrealloc.h
     -ATTR_ALLOC_SIZE(2, 3)
     -ATTR_MALLOC(free)
     -void *xreallocarray(void *p, size_t nmemb, size_t size);
    -+#define XREALLOC(p, n, type)  X(REALLOC(p, n, type))
    ++#define XREALLOC(p, n, type)  x(REALLOC(p, n, type))
      
      
      #endif  // include guard
4:  e4194552 ! 4:  db9916c8 lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of X()
    +    lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of x()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/string/sprintf/xaprintf.h
     -
     -  return p;
     -}
    -+#define xaprintf(...)  X(aprintf(__VA_ARGS__))
    ++#define xaprintf(...)  x(aprintf(__VA_ARGS__))
      
      
      #endif  // include guard
5:  651a7831 ! 5:  418b1799 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/strdup/: XSTRNDUP(): Reimplement in terms of X()
    +    lib/string/strdup/: XSTRNDUP(): Reimplement in terms of x()
     
         This is much simpler.
     
    @@ lib/string/strdup/xstrndup.h
     -(                                                                             \
     -  STRNCAT(strcpy(XMALLOC(strnlen(s, countof(s)) + 1, char), ""), s)     \
     -)
    -+#define XSTRNDUP(s)  X(strndup(s, countof(s)))
    ++#define XSTRNDUP(s)  x(strndup(s, countof(s)))
      
      
      #endif  // include guard
6:  8057a211 ! 6:  4ab76532 lib/string/strdup/xstrndup.h: Add STRNDUP()
    @@ lib/string/strdup/xstrndup.h
      
      
     -// Similar to strndup(3), but ensure that 's' is an array, and exit on ENOMEM.
    --#define XSTRNDUP(s)  X(strndup(s, countof(s)))
    +-#define XSTRNDUP(s)  x(strndup(s, countof(s)))
     +// Similar to strndup(3), but ensure that 's' is an array.
     +#define STRNDUP(s)   strndup(s, countof(s))
     +
    -+// Similar to STRNDUP(), but exit on ENOMEM.
    -+#define XSTRNDUP(s)  X(STRNDUP(s))
    ++// exit-on-error nonstring duplicate-into-string
    ++#define XSTRNDUP(s)  x(STRNDUP(s))
      
      
      #endif  // include guard
7:  46518c4d ! 7:  555972ad lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/strtok/: xastrsep2ls() Reimplement in terms of X()
    +    lib/string/strtok/: xastrsep2ls() Reimplement in terms of x()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/string/strtok/xastrsep2ls.h
     -          log_get_progname(), strerror(errno));
     -  exit(13);
     -}
    -+#define xastrsep2ls(s, delim, np)  X(astrsep2ls(s, delim, np))
    ++#define xastrsep2ls(s, delim, np)  x(astrsep2ls(s, delim, np))
      
      
      #endif  // include guard
8:  3fb734f1 ! 8:  913284e5 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/alloc/calloc.h
      )
      
      
    -+#define XCALLOC(n, type)  X(CALLOC(n, type))
    ++#define XCALLOC(n, type)  x(CALLOC(n, type))
     +
     +
      #endif  // include guard
    @@ lib/alloc/malloc.h
      )
      
      
    -+#define XMALLOC(n, type)  X(MALLOC(n, type))
    ++#define XMALLOC(n, type)  x(MALLOC(n, type))
     +
     +
      ATTR_ALLOC_SIZE(1, 2)
    @@ lib/alloc/realloc.h
      )
      
      
    -+#define XREALLOC(p, n, type)  X(REALLOC(p, n, type))
    ++#define XREALLOC(p, n, type)  x(REALLOC(p, n, type))
     +
     +
      #endif  // include guard
    @@ lib/alloc/x/xcalloc.h (deleted)
     -#include "x.h"
     -
     -
    --#define XCALLOC(n, type)  X(CALLOC(n, type))
    +-#define XCALLOC(n, type)  x(CALLOC(n, type))
     -
     -
     -#endif  // include guard
    @@ lib/alloc/x/xmalloc.h (deleted)
     -#include "x.h"
     -
     -
    --#define XMALLOC(n, type)  X(MALLOC(n, type))
    +-#define XMALLOC(n, type)  x(MALLOC(n, type))
     -
     -
     -#endif  // include guard
    @@ lib/alloc/x/xrealloc.h (deleted)
     -#include "x.h"
     -
     -
    --#define XREALLOC(p, n, type)  X(REALLOC(p, n, type))
    +-#define XREALLOC(p, n, type)  x(REALLOC(p, n, type))
     -
     -
     -#endif  // include guard
    @@ lib/string/sprintf/aprintf.h
     +
     +
     +// exit-on-error allocate print formatted
    -+#define xaprintf(...)  X(aprintf(__VA_ARGS__))
    ++#define xaprintf(...)  x(aprintf(__VA_ARGS__))
      
      
      ATTR_MALLOC(free)
    @@ lib/string/sprintf/xaprintf.h (deleted)
     -
     -
     -// exit-on-error allocate print formatted
    --#define xaprintf(...)  X(aprintf(__VA_ARGS__))
    +-#define xaprintf(...)  x(aprintf(__VA_ARGS__))
     -
     -
     -#endif  // include guard
    @@ lib/string/strtok/astrsep2ls.h
     +#include "x.h"
     +
     +
    -+#define xastrsep2ls(s, delim, np)  X(astrsep2ls(s, delim, np))
    ++#define xastrsep2ls(s, delim, np)  x(astrsep2ls(s, delim, np))
      
      
      ATTR_ACCESS(read_write, 1) ATTR_ACCESS(write_only, 3)
    @@ lib/string/strtok/xastrsep2ls.h (deleted)
     -#include "x.h"
     -
     -
    --#define xastrsep2ls(s, delim, np)  X(astrsep2ls(s, delim, np))
    +-#define xastrsep2ls(s, delim, np)  x(astrsep2ls(s, delim, np))
     -
     -
     -#endif  // include guard
v5b
  • Add some comments documenting xstrdup(), and x() (especially this one). [@ikerexxe ]
$ git range-diff b6189fd1349f^ gh/x x 
1:  b6189fd1 ! 1:  f5516f70 lib/: x(): Add macro to exit() on error
    @@ lib/x.h (new)
     +#include "shadowlog.h"
     +
     +
    ++/*
    ++ * This macro is used for implementing x*() variants of functions that
    ++ * allocate memory, such as xstrdup() for wrapping strdup(3).  The macro
    ++ * returns the input pointer transparently, with the same type, but
    ++ * calls exit(3) if the input is a null pointer (thus, if the allocation
    ++ * failed).
    ++ */
    ++// x - exit-on-error
     +#define x(p)                                                          \
     +({                                                                    \
     +  __auto_type  p_ = p;                                          \
2:  bdcc2abe ! 2:  d988d96a lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of x()
    @@ lib/string/strdup/xstrdup.h
     -{
     -  return strcpy(XMALLOC(strlen(str) + 1, char), str);
     -}
    ++// xstrdup - exit-on-error string duplicate
     +#define xstrdup(s)  x(strdup(s))
      
      
3:  9ca44660 = 3:  632fa619 lib/alloc/x/: X*ALLOC(): Reimplement in terms of x()
4:  db9916c8 = 4:  720c7e39 lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of x()
5:  418b1799 = 5:  cde26407 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of x()
6:  4ab76532 = 6:  6c1e0bd7 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  555972ad = 7:  0933a7d1 lib/string/strtok/: xastrsep2ls() Reimplement in terms of x()
8:  913284e5 = 8:  a27d28f6 lib/, src/, tests/: Move x*() definitions to non-x* header files
v5c
  • Rebase
$ git range-diff f5516f702da5^..gh/x shadow/master..x
1:  f5516f70 = 1:  f7b9e06c lib/: x(): Add macro to exit() on error
2:  d988d96a = 2:  a6ee1e8f lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of x()
3:  632fa619 = 3:  4af2de48 lib/alloc/x/: X*ALLOC(): Reimplement in terms of x()
4:  720c7e39 = 4:  1ebae7be lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of x()
5:  cde26407 = 5:  e7d1f81a lib/string/strdup/: XSTRNDUP(): Reimplement in terms of x()
6:  6c1e0bd7 = 6:  68e98131 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  0933a7d1 = 7:  ef3ff050 lib/string/strtok/: xastrsep2ls() Reimplement in terms of x()
8:  a27d28f6 = 8:  8dd19542 lib/, src/, tests/: Move x*() definitions to non-x* header files
v6
  • Rename x() => exit_if_null(). [@ikerexxe ]
  • Update minor comments describing APIs.
$ git range-diff shadow/master gh/x x 
1:  f7b9e06c ! 1:  de1c1de6 lib/: x(): Add macro to exit() on error
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/: x(): Add macro to exit() on error
    +    lib/x.[ch]: exit_if_null(): Add macro to exit() on error
     
    -    Writing an x*() variant of several functions is unnecessary.  It's
    -    simpler to write a generic x() macro that can be chained with any other
    -    calls.
    +    Writing an x*() variant function of several functions is unnecessary.
    +    It's simpler to write a generic exit_if_null() macro that can be chained
    +    with any other calls.  With such a macro, the x*() variants can be
    +    implemented as one-liner macros that are much easier to read:
     
         For example:
     
    -            -  x(malloc(...)) instead of xmalloc(...);
    -            -  x(strdup(...)) instead of xstrdup(...);
    +            #define xmalloc(size)  exit_if_null(malloc(size))
     
         If an error is detected, log an error, and exit(13).  About why 13, I
         don't really know.  It's just what was used previously in xmalloc().
    @@ lib/x.c (new)
     +#include "x.h"
     +
     +
    -+extern inline void exit_if_null(void *p);
    ++extern inline void exit_if_null_(void *p);
     
      ## lib/x.h (new) ##
     @@
    @@ lib/x.h (new)
     + * calls exit(3) if the input is a null pointer (thus, if the allocation
     + * failed).
     + */
    -+// x - exit-on-error
    -+#define x(p)                                                          \
    ++#define exit_if_null(p)                                               \
     +({                                                                    \
     +  __auto_type  p_ = p;                                          \
     +                                                                      \
    -+  exit_if_null(p_);                                             \
    ++  exit_if_null_(p_);                                            \
     +  p_;                                                           \
     +})
     +
     +
    -+inline void exit_if_null(void *p);
    ++inline void exit_if_null_(void *p);
     +
     +
     +inline void
    -+exit_if_null(void *p)
    ++exit_if_null_(void *p)
     +{
     +  if (p == NULL) {
     +          fprintf(log_get_logfd(), "%s: %s\n",
2:  a6ee1e8f ! 2:  174de7f9 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of x()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of x()
    +    lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of exit_if_null()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/string/strdup/xstrdup.h
     -  return strcpy(XMALLOC(strlen(str) + 1, char), str);
     -}
     +// xstrdup - exit-on-error string duplicate
    -+#define xstrdup(s)  x(strdup(s))
    ++#define xstrdup(s)  exit_if_null(strdup(s))
      
      
      #endif  // include guard
3:  4af2de48 ! 3:  0dd098dd lib/alloc/x/: X*ALLOC(): Reimplement in terms of x()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/alloc/x/: X*ALLOC(): Reimplement in terms of x()
    +    lib/alloc/x/: X*ALLOC(): Reimplement in terms of exit_if_null()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/alloc/x/xcalloc.h
     -ATTR_ALLOC_SIZE(1, 2)
     -ATTR_MALLOC(free)
     -void *xcalloc(size_t nmemb, size_t size);
    -+#define XCALLOC(n, type)  x(CALLOC(n, type))
    ++#define XCALLOC(n, type)  exit_if_null(CALLOC(n, type))
      
      
      #endif  // include guard
    @@ lib/alloc/x/xmalloc.h
     -{
     -  return xreallocarray(NULL, nmemb, size);
     -}
    -+#define XMALLOC(n, type)  x(MALLOC(n, type))
    ++#define XMALLOC(n, type)  exit_if_null(MALLOC(n, type))
      
      
      #endif  // include guard
    @@ lib/alloc/x/xrealloc.h
     -ATTR_ALLOC_SIZE(2, 3)
     -ATTR_MALLOC(free)
     -void *xreallocarray(void *p, size_t nmemb, size_t size);
    -+#define XREALLOC(p, n, type)  x(REALLOC(p, n, type))
    ++#define XREALLOC(p, n, type)  exit_if_null(REALLOC(p, n, type))
      
      
      #endif  // include guard
4:  1ebae7be ! 4:  97b9871e lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of x()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of x()
    +    lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of exit_if_null()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/string/sprintf/xaprintf.h
     -
     -  return p;
     -}
    -+#define xaprintf(...)  x(aprintf(__VA_ARGS__))
    ++#define xaprintf(...)  exit_if_null(aprintf(__VA_ARGS__))
      
      
      #endif  // include guard
5:  e7d1f81a ! 5:  fa2ebe56 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of x()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/strdup/: XSTRNDUP(): Reimplement in terms of x()
    +    lib/string/strdup/: XSTRNDUP(): Reimplement in terms of exit_if_null()
     
         This is much simpler.
     
    @@ lib/string/strdup/xstrndup.h
     -(                                                                             \
     -  STRNCAT(strcpy(XMALLOC(strnlen(s, countof(s)) + 1, char), ""), s)     \
     -)
    -+#define XSTRNDUP(s)  x(strndup(s, countof(s)))
    ++#define XSTRNDUP(s)  exit_if_null(strndup(s, countof(s)))
      
      
      #endif  // include guard
6:  68e98131 ! 6:  3456510c lib/string/strdup/xstrndup.h: Add STRNDUP()
    @@ lib/string/strdup/xstrndup.h
      
      
     -// Similar to strndup(3), but ensure that 's' is an array, and exit on ENOMEM.
    --#define XSTRNDUP(s)  x(strndup(s, countof(s)))
    +-#define XSTRNDUP(s)  exit_if_null(strndup(s, countof(s)))
     +// Similar to strndup(3), but ensure that 's' is an array.
     +#define STRNDUP(s)   strndup(s, countof(s))
     +
     +// exit-on-error nonstring duplicate-into-string
    -+#define XSTRNDUP(s)  x(STRNDUP(s))
    ++#define XSTRNDUP(s)  exit_if_null(STRNDUP(s))
      
      
      #endif  // include guard
7:  ef3ff050 ! 7:  b598dc96 lib/string/strtok/: xastrsep2ls() Reimplement in terms of x()
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/string/strtok/: xastrsep2ls() Reimplement in terms of x()
    +    lib/string/strtok/: xastrsep2ls() Reimplement in terms of exit_if_null()
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    @@ lib/string/strtok/xastrsep2ls.h
     -          log_get_progname(), strerror(errno));
     -  exit(13);
     -}
    -+#define xastrsep2ls(s, delim, np)  x(astrsep2ls(s, delim, np))
    ++#define xastrsep2ls(s, delim, np)  exit_if_null(astrsep2ls(s, delim, np))
      
      
      #endif  // include guard
8:  8dd19542 ! 8:  6f1060f4 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/alloc/calloc.h
      )
      
      
    -+#define XCALLOC(n, type)  x(CALLOC(n, type))
    ++#define XCALLOC(n, type)  exit_if_null(CALLOC(n, type))
     +
     +
      #endif  // include guard
    @@ lib/alloc/malloc.h
      )
      
      
    -+#define XMALLOC(n, type)  x(MALLOC(n, type))
    ++#define XMALLOC(n, type)  exit_if_null(MALLOC(n, type))
     +
     +
      ATTR_ALLOC_SIZE(1, 2)
    @@ lib/alloc/realloc.h
      )
      
      
    -+#define XREALLOC(p, n, type)  x(REALLOC(p, n, type))
    ++#define XREALLOC(p, n, type)  exit_if_null(REALLOC(p, n, type))
     +
     +
      #endif  // include guard
    @@ lib/alloc/x/xcalloc.h (deleted)
     -#include "x.h"
     -
     -
    --#define XCALLOC(n, type)  x(CALLOC(n, type))
    +-#define XCALLOC(n, type)  exit_if_null(CALLOC(n, type))
     -
     -
     -#endif  // include guard
    @@ lib/alloc/x/xmalloc.h (deleted)
     -#include "x.h"
     -
     -
    --#define XMALLOC(n, type)  x(MALLOC(n, type))
    +-#define XMALLOC(n, type)  exit_if_null(MALLOC(n, type))
     -
     -
     -#endif  // include guard
    @@ lib/alloc/x/xrealloc.h (deleted)
     -#include "x.h"
     -
     -
    --#define XREALLOC(p, n, type)  x(REALLOC(p, n, type))
    +-#define XREALLOC(p, n, type)  exit_if_null(REALLOC(p, n, type))
     -
     -
     -#endif  // include guard
    @@ lib/string/sprintf/aprintf.h
     +
     +
     +// exit-on-error allocate print formatted
    -+#define xaprintf(...)  x(aprintf(__VA_ARGS__))
    ++#define xaprintf(...)  exit_if_null(aprintf(__VA_ARGS__))
      
      
      ATTR_MALLOC(free)
    @@ lib/string/sprintf/xaprintf.h (deleted)
     -
     -
     -// exit-on-error allocate print formatted
    --#define xaprintf(...)  x(aprintf(__VA_ARGS__))
    +-#define xaprintf(...)  exit_if_null(aprintf(__VA_ARGS__))
     -
     -
     -#endif  // include guard
    @@ lib/string/strtok/astrsep2ls.h
     +#include "x.h"
     +
     +
    -+#define xastrsep2ls(s, delim, np)  x(astrsep2ls(s, delim, np))
    ++// xastrsep2ls - exit-on-error allocate string separate to list-of-strings
    ++#define xastrsep2ls(s, delim, np)  exit_if_null(astrsep2ls(s, delim, np))
      
      
      ATTR_ACCESS(read_write, 1) ATTR_ACCESS(write_only, 3)
    +@@ lib/string/strtok/astrsep2ls.h: inline char **astrsep2ls(char *restrict s, const char *restrict delim,
    +     size_t *restrict np);
    + 
    + 
    +-// allocate string separate to list-of-strings
    +-// Like strsep2ls(), but allocate the list array.
    ++// astrsep2ls - allocate string separate to list-of-strings
    + inline char **
    + astrsep2ls(char *s, const char *restrict delim, size_t *restrict np)
    + {
     
      ## lib/string/strtok/xastrsep2ls.c (deleted) ##
     @@
    @@ lib/string/strtok/xastrsep2ls.h (deleted)
     -#include "x.h"
     -
     -
    --#define xastrsep2ls(s, delim, np)  x(astrsep2ls(s, delim, np))
    +-#define xastrsep2ls(s, delim, np)  exit_if_null(astrsep2ls(s, delim, np))
     -
     -
     -#endif  // include guard
v6b
  • Rebase
$ git rd 
1:  de1c1de6 = 1:  1ada8c51 lib/x.[ch]: exit_if_null(): Add macro to exit() on error
2:  174de7f9 = 2:  596db941 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of exit_if_null()
3:  0dd098dd = 3:  63792b60 lib/alloc/x/: X*ALLOC(): Reimplement in terms of exit_if_null()
4:  97b9871e = 4:  a20b8446 lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of exit_if_null()
5:  fa2ebe56 = 5:  19c8e9f4 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of exit_if_null()
6:  3456510c = 6:  fde99284 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  b598dc96 = 7:  d9f92f49 lib/string/strtok/: xastrsep2ls() Reimplement in terms of exit_if_null()
8:  6f1060f4 ! 8:  0e6904b2 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ src/chfn.c
     -#include "string/strdup/xstrdup.h"
     +#include "string/strdup/strdup.h"
      
    - 
    - /*
    + struct option_flags {
    +   bool chroot;
     
      ## src/chsh.c ##
     @@
    @@ src/gpasswd.c
     -#include "string/strdup/xstrdup.h"
     +#include "string/strdup/strdup.h"
      
    - 
    - /*
    + struct option_flags {
    +   bool chroot;
     
      ## src/groupmems.c ##
     @@
v6c
  • Rebase
$ git rd 
1:  1ada8c51 = 1:  b3fe40b5 lib/x.[ch]: exit_if_null(): Add macro to exit() on error
2:  596db941 = 2:  584d0500 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of exit_if_null()
3:  63792b60 = 3:  1adfe06f lib/alloc/x/: X*ALLOC(): Reimplement in terms of exit_if_null()
4:  a20b8446 = 4:  ded51456 lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of exit_if_null()
5:  19c8e9f4 = 5:  9b7ca0fe lib/string/strdup/: XSTRNDUP(): Reimplement in terms of exit_if_null()
6:  fde99284 = 6:  06f47f31 lib/string/strdup/xstrndup.h: Add STRNDUP()
7:  d9f92f49 = 7:  4ab75bee lib/string/strtok/: xastrsep2ls() Reimplement in terms of exit_if_null()
8:  0e6904b2 ! 8:  a333a6b0 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ src/login.c
      #include "chkname.h"
      #include "defines.h"
     @@
    - #include "string/strcmp/streq.h"
    + #include "string/strcmp/strneq.h"
      #include "string/strcmp/strprefix.h"
      #include "string/strcpy/strtcpy.h"
     -#include "string/strdup/xstrdup.h"
v7
$ git range-diff shadow/master gh/x x 
1:  b3fe40b5 ! 1:  63bcdc43 lib/x.[ch]: exit_if_null(): Add macro to exit() on error
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/x.[ch]: exit_if_null(): Add macro to exit() on error
    +    lib/: exit_if_null(): Add macro to exit(3) on error
     
         Writing an x*() variant function of several functions is unnecessary.
         It's simpler to write a generic exit_if_null() macro that can be chained
    @@ Commit message
     
      ## lib/Makefile.am ##
     @@ lib/Makefile.am: libshadow_la_SOURCES = \
    -   user_busy.c \
    -   valid.c \
    -   write_full.c \
    -+  x.c \
    -+  x.h \
    -   xgetpwnam.c \
    -   xprefix_getpwnam.c \
    -   xgetpwuid.c \
    +   defines.h \
    +   encrypt.c \
    +   env.c \
    ++  exit_if_null.c \
    ++  exit_if_null.h \
    +   exitcodes.h \
    +   faillog.h \
    +   failure.c \
     
    - ## lib/x.c (new) ##
    + ## lib/exit_if_null.c (new) ##
     @@
     +// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <[email protected]>
     +// SPDX-License-Identifier: BSD-3-Clause
    @@ lib/x.c (new)
     +
     +#include "config.h"
     +
    -+#include "x.h"
    ++#include "exit_if_null.h"
     +
     +
     +extern inline void exit_if_null_(void *p);
     
    - ## lib/x.h (new) ##
    + ## lib/exit_if_null.h (new) ##
     @@
     +// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <[email protected]>
     +// SPDX-License-Identifier: BSD-3-Clause
     +
     +
    -+#ifndef SHADOW_INCLUDE_LIB_X_H_
    -+#define SHADOW_INCLUDE_LIB_X_H_
    ++#ifndef SHADOW_INCLUDE_LIB_EXIT_IF_NULL_H_
    ++#define SHADOW_INCLUDE_LIB_EXIT_IF_NULL_H_
     +
     +
     +#include "config.h"
2:  584d0500 ! 2:  d1603592 lib/string/strdup/: xstrdup(): Reimplement xstrdup() in terms of exit_if_null()
    @@ lib/string/strdup/xstrdup.h
      
     -#include "alloc/x/xmalloc.h"
     -#include "attr.h"
    -+#include "x.h"
    ++#include "exit_if_null.h"
      
      
     -ATTR_MALLOC(free)
3:  1adfe06f ! 3:  3465d621 lib/alloc/x/: X*ALLOC(): Reimplement in terms of exit_if_null()
    @@ lib/alloc/x/xcalloc.h
     -
     -#include "attr.h"
     +#include "alloc/calloc.h"
    -+#include "x.h"
    ++#include "exit_if_null.h"
      
      
     -#define XCALLOC(n, type)                                                      \
    @@ lib/alloc/x/xmalloc.h
     -#include "alloc/x/xrealloc.h"
     -#include "attr.h"
     +#include "alloc/malloc.h"
    -+#include "x.h"
    ++#include "exit_if_null.h"
      
      
     -#define XMALLOC(n, type)                                                      \
    @@ lib/alloc/x/xrealloc.h
     -
     -#include "attr.h"
     +#include "alloc/realloc.h"
    -+#include "x.h"
    ++#include "exit_if_null.h"
      
      
     -#define XREALLOC(ptr, n, type)                                                \
4:  ded51456 ! 4:  b5219503 lib/string/sprintf/, tests/: xaprintf(): Reimplement in terms of exit_if_null()
    @@ lib/string/sprintf/xaprintf.h
     -ATTR_MALLOC(free)
     -format_attr(printf, 1, 0)
     -inline char *xvaprintf(const char *restrict fmt, va_list ap);
    -+#include "x.h"
    ++#include "exit_if_null.h"
      
      
      // exit-on-error allocate print formatted
    @@ tests/unit/Makefile.am: test_typetraits_LDADD = \
          $(NULL)
      
      test_xaprintf_SOURCES = \
    ++    ../../lib/exit_if_null.c \
     +    ../../lib/shadowlog.c \
          ../../lib/string/sprintf/aprintf.c \
          ../../lib/string/sprintf/xaprintf.c \
          ../../lib/string/strcmp/streq.c \
    -+    ../../lib/x.c \
    -     test_xaprintf.c \
    -     $(NULL)
    - test_xaprintf_CFLAGS = \
5:  9b7ca0fe ! 5:  65369725 lib/string/strdup/: XSTRNDUP(): Reimplement in terms of exit_if_null()
    @@ lib/string/strdup/xstrndup.h
     -#include "alloc/x/xmalloc.h"
      #include "sizeof.h"
     -#include "string/strcpy/strncat.h"
    -+#include "x.h"
    ++#include "exit_if_null.h"
      
      
      // Similar to strndup(3), but ensure that 's' is an array, and exit on ENOMEM.
6:  06f47f31 ! 6:  9bce3a2a lib/string/strdup/xstrndup.h: Add STRNDUP()
    @@ Commit message
     
      ## lib/string/strdup/xstrndup.h ##
     @@
    - #include "x.h"
    + #include "exit_if_null.h"
      
      
     -// Similar to strndup(3), but ensure that 's' is an array, and exit on ENOMEM.
7:  4ab75bee ! 7:  4c2b719f lib/string/strtok/: xastrsep2ls() Reimplement in terms of exit_if_null()
    @@ lib/string/strtok/xastrsep2ls.h
     -
     -#include "attr.h"
     -#include "shadowlog.h"
    ++#include "exit_if_null.h"
      #include "string/strtok/astrsep2ls.h"
    -+#include "x.h"
      
      
     -ATTR_ACCESS(read_write, 1) ATTR_ACCESS(write_only, 3)
8:  a333a6b0 ! 8:  c3f91187 lib/, src/, tests/: Move x*() definitions to non-x* header files
    @@ lib/alloc/calloc.h
      
      #include <stdlib.h>
      
    -+#include "x.h"
    ++#include "exit_if_null.h"
     +
      
      #define CALLOC(n, type)                                                       \
    @@ lib/alloc/malloc.h
      #include <stdlib.h>
      
      #include "attr.h"
    -+#include "x.h"
    ++#include "exit_if_null.h"
      
      
      #define MALLOC(n, type)                                                       \
    @@ lib/alloc/realloc.h
      
      
     @@
    - #include "config.h"
      
      #include <stdlib.h>
    -+#include "x.h"
      
    ++#include "exit_if_null.h"
    ++
      
      #define REALLOC(p, n, type)                                                   \
    + (                                                                             \
     @@
      )
      
    @@ lib/alloc/x/xcalloc.h (deleted)
     -#include "config.h"
     -
     -#include "alloc/calloc.h"
    --#include "x.h"
    +-#include "exit_if_null.h"
     -
     -
     -#define XCALLOC(n, type)  exit_if_null(CALLOC(n, type))
    @@ lib/alloc/x/xmalloc.h (deleted)
     -#include "config.h"
     -
     -#include "alloc/malloc.h"
    --#include "x.h"
    +-#include "exit_if_null.h"
     -
     -
     -#define XMALLOC(n, type)  exit_if_null(MALLOC(n, type))
    @@ lib/alloc/x/xrealloc.h (deleted)
     -#include "config.h"
     -
     -#include "alloc/realloc.h"
    --#include "x.h"
    +-#include "exit_if_null.h"
     -
     -
     -#define XREALLOC(p, n, type)  exit_if_null(REALLOC(p, n, type))
    @@ lib/string/sprintf/aprintf.h
      #include <stdlib.h>
      
      #include "attr.h"
    -+#include "x.h"
    ++#include "exit_if_null.h"
     +
     +
     +// exit-on-error allocate print formatted
    @@ lib/string/sprintf/xaprintf.h (deleted)
     -#include "config.h"
     -
     -#include "string/sprintf/aprintf.h"
    --#include "x.h"
    +-#include "exit_if_null.h"
     -
     -
     -// exit-on-error allocate print formatted
    @@ lib/string/strtok/astrsep2ls.h
      
      
     @@
    + 
    + #include "alloc/malloc.h"
      #include "attr.h"
    ++#include "exit_if_null.h"
      #include "string/strchr/strchrscnt.h"
      #include "string/strtok/strsep2ls.h"
    -+#include "x.h"
    -+
    -+
    + 
    + 
     +// xastrsep2ls - exit-on-error allocate string separate to list-of-strings
     +#define xastrsep2ls(s, delim, np)  exit_if_null(astrsep2ls(s, delim, np))
    - 
    - 
    ++
    ++
      ATTR_ACCESS(read_write, 1) ATTR_ACCESS(write_only, 3)
    -@@ lib/string/strtok/astrsep2ls.h: inline char **astrsep2ls(char *restrict s, const char *restrict delim,
    + ATTR_STRING(1) ATTR_STRING(2)
    + inline char **astrsep2ls(char *restrict s, const char *restrict delim,
          size_t *restrict np);
      
      
    @@ lib/string/strtok/xastrsep2ls.h (deleted)
     -
     -#include "config.h"
     -
    +-#include "exit_if_null.h"
     -#include "string/strtok/astrsep2ls.h"
    --#include "x.h"
     -
     -
     -#define xastrsep2ls(s, delim, np)  exit_if_null(astrsep2ls(s, delim, np))
    @@ src/vipw.c
      
     
      ## tests/unit/Makefile.am ##
    -@@ tests/unit/Makefile.am: test_typetraits_LDADD = \
    - test_xaprintf_SOURCES = \
    +@@ tests/unit/Makefile.am: test_xaprintf_SOURCES = \
    +     ../../lib/exit_if_null.c \
          ../../lib/shadowlog.c \
          ../../lib/string/sprintf/aprintf.c \
     -    ../../lib/string/sprintf/xaprintf.c \
          ../../lib/string/strcmp/streq.c \
    -     ../../lib/x.c \
          test_xaprintf.c \
    +     $(NULL)
     
      ## tests/unit/test_xaprintf.c ##
     @@

@alejandro-colomar
Copy link
Collaborator Author

@ikerexxe , @hallyn , I've moved this one to the top of the priority list. I think it's relatively simple, and gets rid of a lot of code, so it's an easy win. Please have a look at it when you can.

Copy link
Collaborator

@ikerexxe ikerexxe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned about the development path that led us here. This PR effectively reverts a significant amount of refactoring that was done just a few months ago.

The problem

Looking at the recent history, we've had two opposing architectural shifts in a very short time:

  • Phase 1 (June 2024 - Jan 2025): a concerted effort was made to modularize these helper functions. They were intentionally moved into dedicated files (lib/alloc/x/, lib/string/strdup/xstrdup.c, etc.) across several commits (29f4f03, 3049bef, 423fd65).
  • Phase 2 (This PR): we are now de-modularizing by removing all those newly created files and consolidating everything into a single macro.

This rapid reversal, while leading to a good end state, is problematic for a few key reasons:

  • Wasted effort: the time developers and reviewers spent on the initial modularization has been nullified. That's a direct cost to the project's velocity.
  • Increased code churn: it introduces noise into the codebase and git history. Future developers looking at the history of these files will see a confusing back-and-forth, making it harder to understand our design philosophy.
  • Architectural instability: it signals a lack of a clear, long-term vision for the codebase's structure. This can make it difficult for contributors to write code that aligns with the project's direction, as that direction appears to change quickly.

This pattern also touches on a broader concern I've raised before about architectural consistency. What's challenging is that we sometimes embark on a promising direction, like the modularization effort, only to reverse it shortly after. When this happens, it becomes difficult to understand the long-term vision and the 'why' behind our structural changes, making it harder for all of us to build with confidence and stay aligned.

By the way, I added some comments inline but I think we should discuss the previous point before.

@alejandro-colomar
Copy link
Collaborator Author

alejandro-colomar commented Oct 16, 2025

I'm concerned about the development path that led us here. This PR effectively reverts a significant amount of refactoring that was done just a few months ago.

The problem

Looking at the recent history, we've had two opposing architectural shifts in a very short time:

  • Phase 1 (June 2024 - Jan 2025): a concerted effort was made to modularize these helper functions. They were intentionally moved into dedicated files (lib/alloc/x/, lib/string/strdup/xstrdup.c, etc.) across several commits (29f4f03, 3049bef, 423fd65).

  • Phase 2 (This PR): we are now de-modularizing by removing all those newly created files and consolidating everything into a single macro.

This rapid reversal, while leading to a good end state, is problematic for a few key reasons:

  • Wasted effort: the time developers and reviewers spent on the initial modularization has been nullified. That's a direct cost to the project's velocity.

That modularization allowed me to see the pattern, and that this macro was possible. In some sense, it has paid off, I think. I regret not having seen that before, though;...

  • Increased code churn: it introduces noise into the codebase and git history. Future developers looking at the history of these files will see a confusing back-and-forth, making it harder to understand our design philosophy.

...I agree this churn could have been prevented if I had seen the possibility of writing this macro earlier. Sometimes, it's hard to see some transformations.

  • Architectural instability: it signals a lack of a clear, long-term vision for the codebase's structure. This can make it difficult for contributors to write code that aligns with the project's direction, as that direction appears to change quickly.

I still want different functions to be in different files, as a general rule.

The differences in this case are

  • These macros are one-liner definitions, where it's harder to justify the overhead of two files for one useful line of code.

  • They always wrap a function that consistently has the same functionality, except for the behavior on error. This makes it meaningful to put both together in the same file.

This pattern also touches on a broader concern I've raised before about architectural consistency. What's challenging is that we sometimes embark on a promising direction, like the modularization effort, only to reverse it shortly after. When this happens, it becomes difficult to understand the long-term vision and the 'why' behind our structural changes, making it harder for all of us to build with confidence and stay aligned.

I'm still in favour of this modularization. I'd consider this a special case, rather than a direction change.

It's similar to the macros for handling arrays, which are also one-liner macro definitions, and which we already define together with the function that they wrap.

@ikerexxe
Copy link
Collaborator

My concern isn't just about the churn in this specific instance, but about the broader pattern and our long-term architectural goals. As I mentioned before our goal is to maintain robust and simple code.

The core issue, as I see it, is the lack of a clear, documented vision for our codebase's structure. You've convincingly argued this is a special case, but the challenge for me is knowing what defines a special case. Without shared principles, it's difficult to review PRs consistently. It leads to situations like this, where well-intentioned efforts seem to contradict each other, and it's hard for anyone on the team to know if they're building in the "right" direction.

This situation highlights the challenge of staying aligned on architectural direction when the guiding principles aren't explicitly defined. A shared understanding of the long-term vision would help ensure we are all building towards the same robust and simple codebase we're aiming for.

@alejandro-colomar
Copy link
Collaborator Author

alejandro-colomar commented Oct 16, 2025

My concern isn't just about the churn in this specific instance, but about the broader pattern and our long-term architectural goals. As I mentioned before our goal is to maintain robust and simple code.

The core issue, as I see it, is the lack of a clear, documented vision for our codebase's structure. You've convincingly argued this is a special case, but the challenge for me is knowing what defines a special case. Without shared principles, it's difficult to review PRs consistently. It leads to situations like this, where well-intentioned efforts seem to contradict each other, and it's hard for anyone on the team to know if they're building in the "right" direction.

This situation highlights the challenge of staying aligned on architectural direction when the guiding principles aren't explicitly defined. A shared understanding of the long-term vision would help ensure we are all building towards the same robust and simple codebase we're aiming for.

My principles for direction of the project would be:

  • Removing code without removing functionality is almost always good.

    github says my line count is +30501, -32028, according to https://github.com/shadow-maint/shadow/graphs/contributors. I'd like to increase the gap between removals and additions.

  • An exception to the rule above is adding higher level interfaces.

    Such higher level interfaces allow reducing the amount of code in most of the code base, while adding some in the actual implementation of the interface. Hopefully, those interfaces will be eventually adopted by libc, which would allow removing them here, and thus reducing further the number of lines of code.

  • Try to avoid repetition, and write APIs to enclose repetition.

    Repetition is prone to accidental divergence, which itself means bugs. With higher level interfaces, it's easier to see patterns, and comparing them to find divergence helps find bugs.

Reducing lines of code isn't good per se; for example, we could remove blank lines, and nothing would be improved. However, if those removals come from using functions to hide code, then the code becomes smaller, and thus more readable. Those APIs need to be well designed to make sense, of course, but I don't think I can write a recipe for guiding API design, other than "try to be consistent".

Some good advise to design APIs is to minimize invention. Try to find existing patterns, and wrap them. Do not try to over-engineer. Consider that those existing patterns enclose old wisdom quite often, so try to understand them and keep that wisdom in the wrapper API.

@hallyn
Copy link
Member

hallyn commented Oct 18, 2025

Overall I agree with Iker, and I had the same thought, "isn't all of this
code that we just added" :)

I do however like the idea of not having separate xZZZ implementations.

Some things I look for when deciding whether something is worth the churn:

If it removes duplicate code, +1.

If it adds testing, without adding overdue burden (e.g. fragile testing
of things which are transient state).

If it makes the code easier to read. Makes it easier to say "yeah, that's
right" or "wait, something's wrong".

If it abstracts away tedious cases or code, which this does.

If it enables the compiler to catch easy to make mistakes. This is where
I've ok'd some changes which I otherwise really didn't like.

Copy link
Member

@hallyn hallyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ikerexxe so despite your general concerns about the overall aimless direction, are you ok with this PR?

@ikerexxe
Copy link
Collaborator

ikerexxe commented Oct 27, 2025

Overall I agree with Iker, and I had the same thought, "isn't all of this code that we just added" :)

I do however like the idea of not having separate xZZZ implementations.

Some things I look for when deciding whether something is worth the churn:

If it removes duplicate code, +1.

If it adds testing, without adding overdue burden (e.g. fragile testing of things which are transient state).

If it makes the code easier to read. Makes it easier to say "yeah, that's right" or "wait, something's wrong".

If it abstracts away tedious cases or code, which this does.

If it enables the compiler to catch easy to make mistakes. This is where I've ok'd some changes which I otherwise really didn't like.

I would like to add that I prioritize testing comprehensiveness - both unit and system-level coverage. Strong test coverage gives us confidence in releases and helps maintain the reliability that system administrators and users depend on.

In addition, for significant architectural changes, I also look for clear justification for any reversals of recent decisions, explicit trade-off analysis, and confidence that this establishes sustainable patterns rather than one-off solutions. This helps ensure we're building toward a coherent long-term architecture rather than making reactive changes.

@ikerexxe so despite your general concerns about the overall aimless direction, are you ok with this PR?

Yes, but I have one last change I'd like to introduce.

@alejandro-colomar one final note before approving, do you mind changing the x.h and x.c filenames to something more meaningful? Probably exit_if_null is clear enough.

@alejandro-colomar
Copy link
Collaborator Author

@ikerexxe so despite your general concerns about the overall aimless direction, are you ok with this PR?

Yes, but I have one last change I'd like to introduce.

@alejandro-colomar one final note before approving, do you mind changing the x.h and x.c filenames to something more meaningful? Probably exit_if_null is clear enough.

Yup, the renaming sounds reasonable, given the updated name of the macro. I'll do in a moment.

Writing an x*() variant function of several functions is unnecessary.
It's simpler to write a generic exit_if_null() macro that can be chained
with any other calls.  With such a macro, the x*() variants can be
implemented as one-liner macros that are much easier to read:

For example:

	#define xmalloc(size)  exit_if_null(malloc(size))

If an error is detected, log an error, and exit(13).  About why 13, I
don't really know.  It's just what was used previously in xmalloc().

Signed-off-by: Alejandro Colomar <[email protected]>
This is much simpler.

Signed-off-by: Alejandro Colomar <[email protected]>
Now that all of these are one-liners, they don't need a separate header
file.  Compact stuff.

Signed-off-by: Alejandro Colomar <[email protected]>
Copy link
Collaborator

@ikerexxe ikerexxe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank your for taking into account the feedback.

@ikerexxe ikerexxe merged commit 655ffcb into shadow-maint:master Oct 27, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants