update from fsf
[gnulib.git] / lib / error.c
1 /* Error handler for noninteractive utilities
2    Copyright (C) 1990,91,92,93,94,95,96,97 Free Software Foundation, Inc.
3
4
5    NOTE: The canonical source of this file is maintained with the GNU C Library.
6    Bugs can be reported to bug-glibc@prep.ai.mit.edu.
7
8    This program is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published by the
10    Free Software Foundation; either version 2, or (at your option) any
11    later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21    USA.  */
22
23 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>.  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30
31 #if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
32 # if __STDC__
33 #  include <stdarg.h>
34 #  define VA_START(args, lastarg) va_start(args, lastarg)
35 # else
36 #  include <varargs.h>
37 #  define VA_START(args, lastarg) va_start(args)
38 # endif
39 #else
40 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8
41 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
42 #endif
43
44 #if STDC_HEADERS || _LIBC
45 # include <stdlib.h>
46 # include <string.h>
47 #else
48 void exit ();
49 #endif
50
51 #include "error.h"
52
53 #ifndef _
54 #define _(String) String
55 #endif
56
57 /* If NULL, error will flush stdout, then print on stderr the program
58    name, a colon and a space.  Otherwise, error will call this
59    function without parameters instead.  */
60 void (*error_print_progname) (
61 #if __STDC__ - 0
62                               void
63 #endif
64                               );
65
66 /* This variable is incremented each time `error' is called.  */
67 unsigned int error_message_count;
68
69 #ifdef _LIBC
70 /* In the GNU C library, there is a predefined variable for this.  */
71
72 #define program_name program_invocation_name
73 #include <errno.h>
74
75 /* In GNU libc we want do not want to use the common name `error' directly.
76    Instead make it a weak alias.  */
77 #define error __error
78 #define error_at_line __error_at_line
79
80 #else
81
82 /* The calling program should define program_name and set it to the
83    name of the executing program.  */
84 extern char *program_name;
85
86 #ifndef HAVE_STRERROR_R
87 # if HAVE_STRERROR
88 #  ifndef strerror              /* On some systems, strerror is a macro */
89 char *strerror ();
90 #  endif
91 # else
92 static char *
93 private_strerror (errnum)
94      int errnum;
95 {
96   extern char *sys_errlist[];
97   extern int sys_nerr;
98
99   if (errnum > 0 && errnum <= sys_nerr)
100     return _(sys_errlist[errnum]);
101   return _("Unknown system error");
102 }
103 #  define strerror private_strerror
104 # endif /* HAVE_STRERROR */
105 #endif  /* HAVE_STRERROR_R */
106 #endif  /* _LIBC */
107
108 /* Print the program name and error message MESSAGE, which is a printf-style
109    format string with optional args.
110    If ERRNUM is nonzero, print its corresponding system error message.
111    Exit with status STATUS if it is nonzero.  */
112 /* VARARGS */
113
114 void
115 #if defined(VA_START) && __STDC__
116 error (int status, int errnum, const char *message, ...)
117 #else
118 error (status, errnum, message, va_alist)
119      int status;
120      int errnum;
121      char *message;
122      va_dcl
123 #endif
124 {
125 #ifdef VA_START
126   va_list args;
127 #endif
128
129   if (error_print_progname)
130     (*error_print_progname) ();
131   else
132     {
133       fflush (stdout);
134       fprintf (stderr, "%s: ", program_name);
135     }
136
137 #ifdef VA_START
138   VA_START (args, message);
139 # if HAVE_VPRINTF || _LIBC
140   vfprintf (stderr, message, args);
141 # else
142   _doprnt (message, args, stderr);
143 # endif
144   va_end (args);
145 #else
146   fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
147 #endif
148
149   ++error_message_count;
150   if (errnum)
151     {
152 #if defined HAVE_STRERROR_R || defined _LIBC
153       char errbuf[1024];
154       fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf));
155 #else
156       fprintf (stderr, ": %s", strerror (errnum));
157 #endif
158     }
159   putc ('\n', stderr);
160   fflush (stderr);
161   if (status)
162     exit (status);
163 }
164 \f
165 /* Sometimes we want to have at most one error per line.  This
166    variable controls whether this mode is selected or not.  */
167 int error_one_per_line;
168
169 void
170 #if defined(VA_START) && __STDC__
171 error_at_line (int status, int errnum, const char *file_name,
172                unsigned int line_number, const char *message, ...)
173 #else
174 error_at_line (status, errnum, file_name, line_number, message, va_alist)
175      int status;
176      int errnum;
177      const char *file_name;
178      unsigned int line_number;
179      char *message;
180      va_dcl
181 #endif
182 {
183 #ifdef VA_START
184   va_list args;
185 #endif
186
187   if (error_one_per_line)
188     {
189       static const char *old_file_name;
190       static unsigned int old_line_number;
191
192       if (old_line_number == line_number &&
193           (file_name == old_file_name || !strcmp (old_file_name, file_name)))
194         /* Simply return and print nothing.  */
195         return;
196
197       old_file_name = file_name;
198       old_line_number = line_number;
199     }
200
201   if (error_print_progname)
202     (*error_print_progname) ();
203   else
204     {
205       fflush (stdout);
206       fprintf (stderr, "%s:", program_name);
207     }
208
209   if (file_name != NULL)
210     fprintf (stderr, "%s:%d: ", file_name, line_number);
211
212 #ifdef VA_START
213   VA_START (args, message);
214 # if HAVE_VPRINTF || _LIBC
215   vfprintf (stderr, message, args);
216 # else
217   _doprnt (message, args, stderr);
218 # endif
219   va_end (args);
220 #else
221   fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
222 #endif
223
224   ++error_message_count;
225   if (errnum)
226     {
227 #if defined HAVE_STRERROR_R || defined _LIBC
228       char errbuf[1024];
229       fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf));
230 #else
231       fprintf (stderr, ": %s", strerror (errnum));
232 #endif
233     }
234   putc ('\n', stderr);
235   fflush (stderr);
236   if (status)
237     exit (status);
238 }
239
240 #ifdef _LIBC
241 /* Make the weak alias.  */
242 #undef error
243 #undef error_at_line
244 weak_alias (__error, error)
245 weak_alias (__error_at_line, error_at_line)
246 #endif