(O_DIRECTORY): Define, if needed.
[gnulib.git] / lib / quotearg.c
index b92d3b6..d5fbc9e 100644 (file)
 size_t mbrtowc ();
 # ifdef mbstate_t
 #  define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
+#  define mbsinit(ps) 1
 # endif
 #else
+/* 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 +92,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 +217,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 +403,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 +466,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,12 +529,17 @@ 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;
+  struct slotvec
     {
       size_t size;
       char *val;
-    } *slotvec;
+    };
+  static struct slotvec slotvec0 = {sizeof slot0, slot0};
+  static struct slotvec *slotvec = &slotvec0;
 
   if (nslots <= n)
     {
@@ -534,6 +547,11 @@ quotearg_n_options (int n, char const *arg,
       size_t s = n1 * sizeof (struct slotvec);
       if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
        abort ();
+      if (slotvec == &slotvec0)
+       {
+         slotvec = (struct slotvec *) xmalloc (sizeof (struct slotvec));
+         *slotvec = slotvec0;
+       }
       slotvec = (struct slotvec *) xrealloc (slotvec, s);
       memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
       nslots = n;
@@ -547,7 +565,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);
       }