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>