File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libiconv / srclib / error.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:57:48 2012 UTC (12 years, 5 months ago) by misho
Branches: libiconv, MAIN
CVS tags: v1_13_1, HEAD
libiconv

    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>