Mercurial > hg-old > index.cgi
comparison lib/error.c @ 272:d5392bb5da3c 2.5
Added generated files
author | lost |
---|---|
date | Sun, 16 Aug 2009 17:16:49 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
271:3b793ba7a6c6 | 272:d5392bb5da3c |
---|---|
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 |