*** empty log message ***
[gnulib.git] / lib / quotearg.c
index 37c2aa3..bd053ee 100644 (file)
@@ -1,5 +1,5 @@
 /* quotearg.c - quote arguments for output
-   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,6 +21,9 @@
 # include <config.h>
 #endif
 
+#if HAVE_STDDEF_H
+# include <stddef.h>  /* For the definition of size_t on windows w/MSVC.  */
+#endif
 #include <sys/types.h>
 #include <quotearg.h>
 #include <xalloc.h>
 #ifndef CHAR_BIT
 # define CHAR_BIT 8
 #endif
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
 #ifndef UCHAR_MAX
 # define UCHAR_MAX ((unsigned char) -1)
 #endif
+#ifndef UINT_MAX
+# define UINT_MAX ((unsigned int) -1)
+#endif
 
 #if HAVE_C_BACKSLASH_A
 # define ALERT_CHAR '\a'
 #endif
 
 #if HAVE_WCHAR_H
+
+/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared.  */
+# include <stdio.h>
+# include <time.h>
+
 # include <wchar.h>
 #endif
 
-#if HAVE_MBRTOWC && HAVE_WCHAR_H
-size_t mbrtowc ();
-# if !HAVE_MBSTATE_T_OBJECT
-#  define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
-# endif
-#else
+#if !HAVE_MBRTOWC
+/* Disable multibyte processing entirely.  Since MB_CUR_MAX is 1, the
+   other macros are defined only for documentation and to satisfy C
+   syntax.  */
+# undef MB_CUR_MAX
+# define MB_CUR_MAX 1
 # define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
 # define mbsinit(ps) 1
 # define iswprint(wc) ISPRINT ((unsigned char) (wc))
@@ -86,15 +100,14 @@ size_t mbrtowc ();
 #define INT_BITS (sizeof (int) * CHAR_BIT)
 
 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
-/* Undefine to protect against the definition in wctype.h of solaris2.6.   */
-# undef ISASCII
-# define ISASCII(c) 1
+# define IN_CTYPE_DOMAIN(c) 1
 #else
-# define ISASCII(c) isascii (c)
+# define IN_CTYPE_DOMAIN(c) isascii(c)
 #endif
+
 /* Undefine to protect against the definition in wctype.h of solaris2.6.   */
 #undef ISPRINT
-#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
 
 struct quoting_options
 {
@@ -212,6 +225,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
   char const *quote_string = 0;
   size_t quote_string_len = 0;
   int backslash_escapes = 0;
+  int unibyte_locale = MB_CUR_MAX == 1;
 
 #define STORE(c) \
     do \
@@ -397,57 +411,59 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
             we can't easily escape single characters within it.  */
          {
            /* Length of multibyte sequence found so far.  */
-           size_t m = 0;
+           size_t m;
 
-           int printable = 1;
-           mbstate_t mbstate;
-           memset (&mbstate, 0, sizeof mbstate);
+           int printable;
 
-           if (argsize == (size_t) -1)
-             argsize = strlen (arg);
-
-           do
+           if (unibyte_locale)
              {
-               wchar_t w;
-               size_t bytes = mbrtowc (&w, &arg[i + m],
-                                       argsize - (i + m), &mbstate);
-               if (bytes == 0)
-                 break;
-               else if (bytes == (size_t) -1)
-                 {
-                   printable = 0;
-                   break;
-                 }
-               else if (bytes == (size_t) -2)
-                 {
-                   printable = 0;
-                   while (i + m < argsize && arg[i + m])
-                     m++;
-                   break;
-                 }
-               else
-                 {
-                   if (! iswprint (w))
-                     printable = 0;
-                   m += bytes;
-                 }
+               m = 1;
+               printable = ISPRINT (c);
              }
-           while (! mbsinit (&mbstate));
-
-           if (m <= 1)
+           else
              {
-               /* Escape a unibyte character like a multibyte
-                  sequence if using backslash escapes, and if the
-                  character is not printable.  */
-               m = backslash_escapes && ! ISPRINT (c);
-               printable = 0;
+               mbstate_t mbstate;
+               memset (&mbstate, 0, sizeof mbstate);
+
+               m = 0;
+               printable = 1;
+               if (argsize == (size_t) -1)
+                 argsize = strlen (arg);
+
+               do
+                 {
+                   wchar_t w;
+                   size_t bytes = mbrtowc (&w, &arg[i + m],
+                                           argsize - (i + m), &mbstate);
+                   if (bytes == 0)
+                     break;
+                   else if (bytes == (size_t) -1)
+                     {
+                       printable = 0;
+                       break;
+                     }
+                   else if (bytes == (size_t) -2)
+                     {
+                       printable = 0;
+                       while (i + m < argsize && arg[i + m])
+                         m++;
+                       break;
+                     }
+                   else
+                     {
+                       if (! iswprint (w))
+                         printable = 0;
+                       m += bytes;
+                     }
+                 }
+               while (! mbsinit (&mbstate));
              }
 
-           if (m)
+           if (1 < m || (backslash_escapes && ! printable))
              {
                /* Output a multibyte sequence, or an escaped
                   unprintable unibyte character.  */
-               size_t imax = i + m - 1;
+               size_t ilim = i + m;
 
                for (;;)
                  {
@@ -458,7 +474,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
                        STORE ('0' + ((c >> 3) & 7));
                        c = '0' + (c & 7);
                      }
-                   if (i == imax)
+                   if (ilim <= i + 1)
                      break;
                    STORE (c);
                    c = arg[++i];
@@ -521,22 +537,39 @@ static char *
 quotearg_n_options (int n, char const *arg,
                    struct quoting_options const *options)
 {
-  static unsigned int nslots;
-  static struct slotvec
+  /* Preallocate a slot 0 buffer, so that the caller can always quote
+     one small component of a "memory exhausted" message in slot 0.  */
+  static char slot0[256];
+  static unsigned int nslots = 1;
+  unsigned int n0 = n;
+  struct slotvec
     {
       size_t size;
       char *val;
-    } *slotvec;
+    };
+  static struct slotvec slotvec0 = {sizeof slot0, slot0};
+  static struct slotvec *slotvec = &slotvec0;
+
+  if (n < 0)
+    abort ();
 
-  if (nslots <= n)
+  if (nslots <= n0)
     {
-      int n1 = n + 1;
-      size_t s = n1 * sizeof (struct slotvec);
-      if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
-       abort ();
+      unsigned int n1 = n0 + 1;
+      size_t s = n1 * sizeof *slotvec;
+
+      if (SIZE_MAX / UINT_MAX <= sizeof *slotvec
+         && n1 != s / sizeof *slotvec)
+       xalloc_die ();
+
+      if (slotvec == &slotvec0)
+       {
+         slotvec = (struct slotvec *) xmalloc (sizeof *slotvec);
+         *slotvec = slotvec0;
+       }
       slotvec = (struct slotvec *) xrealloc (slotvec, s);
-      memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
-      nslots = n;
+      memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec);
+      nslots = n1;
     }
 
   {
@@ -547,7 +580,7 @@ quotearg_n_options (int n, char const *arg,
     if (size <= qsize)
       {
        slotvec[n].size = size = qsize + 1;
-       slotvec[n].val = val = xrealloc (val, size);
+       slotvec[n].val = val = xrealloc (val == slot0 ? 0 : val, size);
        quotearg_buffer (val, size, arg, (size_t) -1, options);
       }
 
@@ -556,7 +589,7 @@ quotearg_n_options (int n, char const *arg,
 }
 
 char *
-quotearg_n (unsigned int n, char const *arg)
+quotearg_n (int n, char const *arg)
 {
   return quotearg_n_options (n, arg, &default_quoting_options);
 }
@@ -568,7 +601,7 @@ quotearg (char const *arg)
 }
 
 char *
-quotearg_n_style (unsigned int n, enum quoting_style s, char const *arg)
+quotearg_n_style (int n, enum quoting_style s, char const *arg)
 {
   struct quoting_options o;
   o.style = s;