Annotation of embedaddon/libiconv/srclib/error.c, revision 1.1
1.1 ! misho 1: /* Error handler for noninteractive utilities
! 2: Copyright (C) 1990-1998, 2000-2007 Free Software Foundation, Inc.
! 3: This file is part of the GNU C Library.
! 4:
! 5: This program is free software: you can redistribute it and/or modify
! 6: it under the terms of the GNU General Public License as published by
! 7: the Free Software Foundation; either version 3 of the License, or
! 8: (at your option) any later version.
! 9:
! 10: This program is distributed in the hope that it will be useful,
! 11: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 13: GNU General Public License for more details.
! 14:
! 15: You should have received a copy of the GNU General Public License
! 16: along with this program. If not, see <http://www.gnu.org/licenses/>. */
! 17:
! 18: /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
! 19:
! 20: #if !_LIBC
! 21: # include <config.h>
! 22: #endif
! 23:
! 24: #include "error.h"
! 25:
! 26: #include <stdarg.h>
! 27: #include <stdio.h>
! 28: #include <stdlib.h>
! 29: #include <string.h>
! 30:
! 31: #if !_LIBC && ENABLE_NLS
! 32: # include "gettext.h"
! 33: # define _(msgid) gettext (msgid)
! 34: #endif
! 35:
! 36: #ifdef _LIBC
! 37: # include <libintl.h>
! 38: # include <stdbool.h>
! 39: # include <stdint.h>
! 40: # include <wchar.h>
! 41: # define mbsrtowcs __mbsrtowcs
! 42: #endif
! 43:
! 44: #if USE_UNLOCKED_IO
! 45: # include "unlocked-io.h"
! 46: #endif
! 47:
! 48: #ifndef _
! 49: # define _(String) String
! 50: #endif
! 51:
! 52: /* If NULL, error will flush stdout, then print on stderr the program
! 53: name, a colon and a space. Otherwise, error will call this
! 54: function without parameters instead. */
! 55: void (*error_print_progname) (void);
! 56:
! 57: /* This variable is incremented each time `error' is called. */
! 58: unsigned int error_message_count;
! 59:
! 60: #ifdef _LIBC
! 61: /* In the GNU C library, there is a predefined variable for this. */
! 62:
! 63: # define program_name program_invocation_name
! 64: # include <errno.h>
! 65: # include <limits.h>
! 66: # include <libio/libioP.h>
! 67:
! 68: /* In GNU libc we want do not want to use the common name `error' directly.
! 69: Instead make it a weak alias. */
! 70: extern void __error (int status, int errnum, const char *message, ...)
! 71: __attribute__ ((__format__ (__printf__, 3, 4)));
! 72: extern void __error_at_line (int status, int errnum, const char *file_name,
! 73: unsigned int line_number, const char *message,
! 74: ...)
! 75: __attribute__ ((__format__ (__printf__, 5, 6)));;
! 76: # define error __error
! 77: # define error_at_line __error_at_line
! 78:
! 79: # include <libio/iolibio.h>
! 80: # define fflush(s) INTUSE(_IO_fflush) (s)
! 81: # undef putc
! 82: # define putc(c, fp) INTUSE(_IO_putc) (c, fp)
! 83:
! 84: # include <bits/libc-lock.h>
! 85:
! 86: #else /* not _LIBC */
! 87:
! 88: # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
! 89: # ifndef HAVE_DECL_STRERROR_R
! 90: "this configure-time declaration test was not run"
! 91: # endif
! 92: char *strerror_r ();
! 93: # endif
! 94:
! 95: /* The calling program should define program_name and set it to the
! 96: name of the executing program. */
! 97: extern char *program_name;
! 98:
! 99: # if HAVE_STRERROR_R || defined strerror_r
! 100: # define __strerror_r strerror_r
! 101: # endif /* HAVE_STRERROR_R || defined strerror_r */
! 102: #endif /* not _LIBC */
! 103:
! 104: static void
! 105: print_errno_message (int errnum)
! 106: {
! 107: char const *s;
! 108:
! 109: #if defined HAVE_STRERROR_R || _LIBC
! 110: char errbuf[1024];
! 111: # if STRERROR_R_CHAR_P || _LIBC
! 112: s = __strerror_r (errnum, errbuf, sizeof errbuf);
! 113: # else
! 114: if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0)
! 115: s = errbuf;
! 116: else
! 117: s = 0;
! 118: # endif
! 119: #else
! 120: s = strerror (errnum);
! 121: #endif
! 122:
! 123: #if !_LIBC
! 124: if (! s)
! 125: s = _("Unknown system error");
! 126: #endif
! 127:
! 128: #if _LIBC
! 129: __fxprintf (NULL, ": %s", s);
! 130: #else
! 131: fprintf (stderr, ": %s", s);
! 132: #endif
! 133: }
! 134:
! 135: static void
! 136: error_tail (int status, int errnum, const char *message, va_list args)
! 137: {
! 138: #if _LIBC
! 139: if (_IO_fwide (stderr, 0) > 0)
! 140: {
! 141: # define ALLOCA_LIMIT 2000
! 142: size_t len = strlen (message) + 1;
! 143: wchar_t *wmessage = NULL;
! 144: mbstate_t st;
! 145: size_t res;
! 146: const char *tmp;
! 147: bool use_malloc = false;
! 148:
! 149: while (1)
! 150: {
! 151: if (__libc_use_alloca (len * sizeof (wchar_t)))
! 152: wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
! 153: else
! 154: {
! 155: if (!use_malloc)
! 156: wmessage = NULL;
! 157:
! 158: wchar_t *p = (wchar_t *) realloc (wmessage,
! 159: len * sizeof (wchar_t));
! 160: if (p == NULL)
! 161: {
! 162: free (wmessage);
! 163: fputws_unlocked (L"out of memory\n", stderr);
! 164: return;
! 165: }
! 166: wmessage = p;
! 167: use_malloc = true;
! 168: }
! 169:
! 170: memset (&st, '\0', sizeof (st));
! 171: tmp = message;
! 172:
! 173: res = mbsrtowcs (wmessage, &tmp, len, &st);
! 174: if (res != len)
! 175: break;
! 176:
! 177: if (__builtin_expect (len >= SIZE_MAX / 2, 0))
! 178: {
! 179: /* This really should not happen if everything is fine. */
! 180: res = (size_t) -1;
! 181: break;
! 182: }
! 183:
! 184: len *= 2;
! 185: }
! 186:
! 187: if (res == (size_t) -1)
! 188: {
! 189: /* The string cannot be converted. */
! 190: if (use_malloc)
! 191: {
! 192: free (wmessage);
! 193: use_malloc = false;
! 194: }
! 195: wmessage = (wchar_t *) L"???";
! 196: }
! 197:
! 198: __vfwprintf (stderr, wmessage, args);
! 199:
! 200: if (use_malloc)
! 201: free (wmessage);
! 202: }
! 203: else
! 204: #endif
! 205: vfprintf (stderr, message, args);
! 206: va_end (args);
! 207:
! 208: ++error_message_count;
! 209: if (errnum)
! 210: print_errno_message (errnum);
! 211: #if _LIBC
! 212: __fxprintf (NULL, "\n");
! 213: #else
! 214: putc ('\n', stderr);
! 215: #endif
! 216: fflush (stderr);
! 217: if (status)
! 218: exit (status);
! 219: }
! 220:
! 221:
! 222: /* Print the program name and error message MESSAGE, which is a printf-style
! 223: format string with optional args.
! 224: If ERRNUM is nonzero, print its corresponding system error message.
! 225: Exit with status STATUS if it is nonzero. */
! 226: void
! 227: error (int status, int errnum, const char *message, ...)
! 228: {
! 229: va_list args;
! 230:
! 231: #if defined _LIBC && defined __libc_ptf_call
! 232: /* We do not want this call to be cut short by a thread
! 233: cancellation. Therefore disable cancellation for now. */
! 234: int state = PTHREAD_CANCEL_ENABLE;
! 235: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
! 236: 0);
! 237: #endif
! 238:
! 239: fflush (stdout);
! 240: #ifdef _LIBC
! 241: _IO_flockfile (stderr);
! 242: #endif
! 243: if (error_print_progname)
! 244: (*error_print_progname) ();
! 245: else
! 246: {
! 247: #if _LIBC
! 248: __fxprintf (NULL, "%s: ", program_name);
! 249: #else
! 250: fprintf (stderr, "%s: ", program_name);
! 251: #endif
! 252: }
! 253:
! 254: va_start (args, message);
! 255: error_tail (status, errnum, message, args);
! 256:
! 257: #ifdef _LIBC
! 258: _IO_funlockfile (stderr);
! 259: # ifdef __libc_ptf_call
! 260: __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
! 261: # endif
! 262: #endif
! 263: }
! 264:
! 265: /* Sometimes we want to have at most one error per line. This
! 266: variable controls whether this mode is selected or not. */
! 267: int error_one_per_line;
! 268:
! 269: void
! 270: error_at_line (int status, int errnum, const char *file_name,
! 271: unsigned int line_number, const char *message, ...)
! 272: {
! 273: va_list args;
! 274:
! 275: if (error_one_per_line)
! 276: {
! 277: static const char *old_file_name;
! 278: static unsigned int old_line_number;
! 279:
! 280: if (old_line_number == line_number
! 281: && (file_name == old_file_name
! 282: || strcmp (old_file_name, file_name) == 0))
! 283: /* Simply return and print nothing. */
! 284: return;
! 285:
! 286: old_file_name = file_name;
! 287: old_line_number = line_number;
! 288: }
! 289:
! 290: #if defined _LIBC && defined __libc_ptf_call
! 291: /* We do not want this call to be cut short by a thread
! 292: cancellation. Therefore disable cancellation for now. */
! 293: int state = PTHREAD_CANCEL_ENABLE;
! 294: __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
! 295: 0);
! 296: #endif
! 297:
! 298: fflush (stdout);
! 299: #ifdef _LIBC
! 300: _IO_flockfile (stderr);
! 301: #endif
! 302: if (error_print_progname)
! 303: (*error_print_progname) ();
! 304: else
! 305: {
! 306: #if _LIBC
! 307: __fxprintf (NULL, "%s:", program_name);
! 308: #else
! 309: fprintf (stderr, "%s:", program_name);
! 310: #endif
! 311: }
! 312:
! 313: #if _LIBC
! 314: __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
! 315: file_name, line_number);
! 316: #else
! 317: fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
! 318: file_name, line_number);
! 319: #endif
! 320:
! 321: va_start (args, message);
! 322: error_tail (status, errnum, message, args);
! 323:
! 324: #ifdef _LIBC
! 325: _IO_funlockfile (stderr);
! 326: # ifdef __libc_ptf_call
! 327: __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
! 328: # endif
! 329: #endif
! 330: }
! 331:
! 332: #ifdef _LIBC
! 333: /* Make the weak alias. */
! 334: # undef error
! 335: # undef error_at_line
! 336: weak_alias (__error, error)
! 337: weak_alias (__error_at_line, error_at_line)
! 338: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>