On 9/19/26 15:13, Andrew L. Moore wrote:
--- shell-quote.c begins here ---
...> --- shell-quote.c ends here ---

It turns out that comparing size_t against long double only only works
with extended-precision floating point (i.e., a 64-bit significand), which
ARM64 platforms don't support (e.g., macOS). So for the sake of
completeness, here's a portable version of shell-quote:

--- shell-quote.c begins here
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

/* Assert: 256 <= BUFSIZ <= 512KB and that 2 ^ BUFSIZ_LOG2 == BUFSIZ */
#define BUFSIZ_LOG2                                                           \
  ((BUFSIZ & 0x100)   ?  8 :                                                  \
   (BUFSIZ & 0x200)   ?  9 :                                                  \
   (BUFSIZ & 0x400)   ? 10 :                                                  \
   (BUFSIZ & 0x800)   ? 11 :                                                  \
   (BUFSIZ & 0x1000)  ? 12 :                                                  \
   (BUFSIZ & 0x2000)  ? 13 :                                                  \
   (BUFSIZ & 0x4000)  ? 14 :                                                  \
   (BUFSIZ & 0x8000)  ? 15 :                                                  \
   (BUFSIZ & 0x10000) ? 16 :                                                  \
   (BUFSIZ & 0x20000) ? 17 :                                                  \
   (BUFSIZ & 0x40000) ? 18 :                                                  \
   (BUFSIZ & 0x80000) ? 19 : -1)

#ifdef HAVE___BUILTIN_UADDL_OVERFLOW
/*
 * REALLOC_ADD_THROW: Assure minimum size `i + j' for buffer `b' with size `n'.
 */
# define REALLOC_ADD_THROW(_b, _n, _i, _j, _err)                              \
  do                                                                          \
    {                                                                         \
      size_t _k = 0;                                                          \
      if (__builtin_uaddl_overflow ((_i), (_j), &_k))                         \
        return (_err);                                                        \
      else if (!realloc_buffer ((void **)&(_b), &(_n), _k))                   \
        return (_err);                                                        \
    }                                                                         \
  while (0)
#else
# define REALLOC_ADD_THROW(_b, _n, _i, _j, _err)                              \
  do                                                                          \
    {                                                                         \
      if ((size_t)(_i) > SIZE_MAX - (_j))                                     \
         return (_err);                                                       \
       else if (!realloc_buffer ((void **)&(_b), &(_n), (_i) + (_j)))         \
        return (_err);                                                        \
    }                                                                         \
  while (0)
#endif  /* !HAVE___BUILTIN_UADDL_OVERFLOW */


static char *shell_quote(const char *fn);
static void *realloc_buffer(void **b, size_t *n, size_t i);

int
main(int argc, char *argv[])
{
  char *s = argv[1];
  printf("Original: %s\nQuoted: %s\n", s, shell_quote(s));
  return 0;
}

/* shell_quote: Return pointer shell-quoted fn: 'lo y'all' => \''lo y'\''all'\' 
*/
static char *
shell_quote (const char *fn)
{
  static char *quoted = NULL;
  static size_t quoted_size = 0;

  size_t len = strlen (fn);

  REALLOC_ADD_THROW (quoted, quoted_size, len, 3, NULL);

  size_t quoted_len = len + 2; /* 'fn' */
  size_t idx = 0;

  if (!len)
    {
      quoted[idx++] = '\'';
      quoted[idx++] = '\'';
      quoted[idx] = '\0';
      return quoted;
    }

  while (*fn == '\'')
    {
      REALLOC_ADD_THROW (quoted, quoted_size, quoted_len, 2, NULL);
      quoted_len += 1;
      quoted[idx++] = '\\';
      quoted[idx++] = '\'';
      ++fn;
    }

  if (*fn)
    quoted[idx++] = '\'';

  for (; *fn; ++fn)
    {
      if (*fn == '\'')
        {
          if (*(fn + 1))
            {
              REALLOC_ADD_THROW (quoted, quoted_size, quoted_len, 4, NULL);
              quoted_len += 3;
              quoted[idx++] = '\'';
              quoted[idx++] = '\\';
              quoted[idx++] = '\'';
              quoted[idx++] = '\'';
            }
          else
            {
              REALLOC_ADD_THROW (quoted, quoted_size, quoted_len, 3, NULL);
              quoted_len += 2;
              quoted[idx++] = '\'';
              quoted[idx++] = '\\';
              quoted[idx++] = '\'';
            }
        }
      else
        {
          if (*(fn + 1))
            {
              quoted[idx++] = *fn;
            }
          else
            {
              quoted[idx++] = *fn;
              quoted[idx++] = '\'';
            }
        }
    }
  quoted[idx] = '\0';
  return quoted;
}

/* realloc_buffer: Increase size, *n, of buffer, *b, to at least i. */
static void *
realloc_buffer (void **b, size_t *n, size_t i)
{
  char *ts;
  size_t ti;

  /*
   * Assert: 0 <= i && i <= SIZE_MAX.
   * NB: Allocate memory if i == *n == 0.
   */
  if (i < *n)
    return *b;
  if (i < BUFSIZ)
    ti = BUFSIZ;
  else if (i >> BUFSIZ_LOG2 <= SIZE_MAX >> (BUFSIZ_LOG2 + 1))
    ti = (size_t) (i >> BUFSIZ_LOG2 << (BUFSIZ_LOG2 + 1));
  else
    ti = i;
  if (!(ts = (char *) realloc (*b, ti)))
    {
      fprintf (stderr, "%s\n", strerror (errno));
      return NULL;
    }
  *n = ti;
  *b = ts;
  return *b;
}
--- shell-quote.c ends here ---



Reply via email to