Annotation of embedaddon/libiconv/srclib/error.c, revision 1.1.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>