have bootstrap initialize git-merge-changelog if found
[gnulib.git] / lib / error.c
index e249942..3177bd5 100644 (file)
@@ -1,24 +1,23 @@
 /* Error handler for noninteractive utilities
-   Copyright (C) 1990-1998, 2000-2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1990-1998, 2000-2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
-   This program is free software; you can redistribute it and/or modify
+   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
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
 
-#ifdef HAVE_CONFIG_H
+#if !_LIBC
 # include <config.h>
 #endif
 
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef _LIBC
-# include <libintl.h>
-#else
+#if !_LIBC && ENABLE_NLS
 # include "gettext.h"
+# define _(msgid) gettext (msgid)
 #endif
 
 #ifdef _LIBC
+# include <libintl.h>
+# include <stdbool.h>
+# include <stdint.h>
 # include <wchar.h>
 # define mbsrtowcs __mbsrtowcs
 #endif
 
-#if !_LIBC
+#if USE_UNLOCKED_IO
 # include "unlocked-io.h"
 #endif
 
@@ -61,6 +62,7 @@ unsigned int error_message_count;
 
 # define program_name program_invocation_name
 # include <errno.h>
+# include <limits.h>
 # include <libio/libioP.h>
 
 /* In GNU libc we want do not want to use the common name `error' directly.
@@ -96,7 +98,7 @@ extern char *program_name;
 
 # if HAVE_STRERROR_R || defined strerror_r
 #  define __strerror_r strerror_r
-# endif
+# endif        /* HAVE_STRERROR_R || defined strerror_r */
 #endif /* not _LIBC */
 
 static void
@@ -124,14 +126,10 @@ print_errno_message (int errnum)
 #endif
 
 #if _LIBC
-  if (_IO_fwide (stderr, 0) > 0)
-    {
-      __fwprintf (stderr, L": %s", s);
-      return;
-    }
-#endif
-
+  __fxprintf (NULL, ": %s", s);
+#else
   fprintf (stderr, ": %s", s);
+#endif
 }
 
 static void
@@ -146,36 +144,61 @@ error_tail (int status, int errnum, const char *message, va_list args)
       mbstate_t st;
       size_t res;
       const char *tmp;
+      bool use_malloc = false;
 
-      do
+      while (1)
        {
-         if (len < ALLOCA_LIMIT)
+         if (__libc_use_alloca (len * sizeof (wchar_t)))
            wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
          else
            {
-             if (wmessage != NULL && len / 2 < ALLOCA_LIMIT)
+             if (!use_malloc)
                wmessage = NULL;
 
-             wmessage = (wchar_t *) realloc (wmessage,
-                                             len * sizeof (wchar_t));
-
-             if (wmessage == NULL)
+             wchar_t *p = (wchar_t *) realloc (wmessage,
+                                               len * sizeof (wchar_t));
+             if (p == NULL)
                {
+                 free (wmessage);
                  fputws_unlocked (L"out of memory\n", stderr);
                  return;
                }
+             wmessage = p;
+             use_malloc = true;
            }
 
          memset (&st, '\0', sizeof (st));
-         tmp =message;
+         tmp = message;
+
+         res = mbsrtowcs (wmessage, &tmp, len, &st);
+         if (res != len)
+           break;
+
+         if (__builtin_expect (len >= SIZE_MAX / 2, 0))
+           {
+             /* This really should not happen if everything is fine.  */
+             res = (size_t) -1;
+             break;
+           }
+
+         len *= 2;
        }
-      while ((res = mbsrtowcs (wmessage, &tmp, len, &st)) == len);
 
       if (res == (size_t) -1)
-       /* The string cannot be converted.  */
-       wmessage = (wchar_t *) L"???";
+       {
+         /* The string cannot be converted.  */
+         if (use_malloc)
+           {
+             free (wmessage);
+             use_malloc = false;
+           }
+         wmessage = (wchar_t *) L"???";
+       }
 
       __vfwprintf (stderr, wmessage, args);
+
+      if (use_malloc)
+       free (wmessage);
     }
   else
 #endif
@@ -186,11 +209,10 @@ error_tail (int status, int errnum, const char *message, va_list args)
   if (errnum)
     print_errno_message (errnum);
 #if _LIBC
-  if (_IO_fwide (stderr, 0) > 0)
-    putwc (L'\n', stderr);
-  else
+  __fxprintf (NULL, "\n");
+#else
+  putc ('\n', stderr);
 #endif
-    putc ('\n', stderr);
   fflush (stderr);
   if (status)
     exit (status);
@@ -223,11 +245,10 @@ error (int status, int errnum, const char *message, ...)
   else
     {
 #if _LIBC
-      if (_IO_fwide (stderr, 0) > 0)
-       __fwprintf (stderr, L"%s: ", program_name);
-      else
+      __fxprintf (NULL, "%s: ", program_name);
+#else
+      fprintf (stderr, "%s: ", program_name);
 #endif
-       fprintf (stderr, "%s: ", program_name);
     }
 
   va_start (args, message);
@@ -283,22 +304,19 @@ error_at_line (int status, int errnum, const char *file_name,
   else
     {
 #if _LIBC
-      if (_IO_fwide (stderr, 0) > 0)
-       __fwprintf (stderr, L"%s: ", program_name);
-      else
+      __fxprintf (NULL, "%s:", program_name);
+#else
+      fprintf (stderr, "%s:", program_name);
 #endif
-       fprintf (stderr, "%s:", program_name);
     }
 
-  if (file_name != NULL)
-    {
 #if _LIBC
-      if (_IO_fwide (stderr, 0) > 0)
-       __fwprintf (stderr, L"%s:%d: ", file_name, line_number);
-      else
+  __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
+             file_name, line_number);
+#else
+  fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
+          file_name, line_number);
 #endif
-       fprintf (stderr, "%s:%d: ", file_name, line_number);
-    }
 
   va_start (args, message);
   error_tail (status, errnum, message, args);