2005-07-07 Francois-Xavier Coudert <coudert@clipper.ens.fr>
[official-gcc.git] / libgfortran / runtime / error.c
blobff91b96bd3f064bf9a43195b680d142bb32e2f79
1 /* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
4 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file. (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
18 executable.)
20 Libgfortran is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with libgfortran; see the file COPYING. If not, write to
27 the Free Software Foundation, 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA. */
31 #include "config.h"
32 #include <stdio.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <float.h>
37 #include "libgfortran.h"
38 #include "../io/io.h"
40 /* Error conditions. The tricky part here is printing a message when
41 * it is the I/O subsystem that is severely wounded. Our goal is to
42 * try and print something making the fewest assumptions possible,
43 * then try to clean up before actually exiting.
45 * The following exit conditions are defined:
46 * 0 Normal program exit.
47 * 1 Terminated because of operating system error.
48 * 2 Error in the runtime library
49 * 3 Internal error in runtime library
50 * 4 Error during error processing (very bad)
52 * Other error returns are reserved for the STOP statement with a numeric code.
55 /* locus variables. These are optionally set by a caller before a
56 * library subroutine is called. They are always cleared on exit so
57 * that files that report loci and those that do not can be linked
58 * together without reporting an erroneous position. */
60 char *filename = 0;
61 iexport_data(filename);
63 unsigned line = 0;
64 iexport_data(line);
66 /* buffer for integer/ascii conversions. */
67 static char buffer[sizeof (GFC_UINTEGER_LARGEST) * 8 + 1];
70 /* Returns a pointer to a static buffer. */
72 char *
73 gfc_itoa (GFC_INTEGER_LARGEST n)
75 int negative;
76 char *p;
77 GFC_UINTEGER_LARGEST t;
79 if (n == 0)
81 buffer[0] = '0';
82 buffer[1] = '\0';
83 return buffer;
86 negative = 0;
87 t = n;
88 if (n < 0)
90 negative = 1;
91 t = -n; /*must use unsigned to protect from overflow*/
94 p = buffer + sizeof (buffer) - 1;
95 *p-- = '\0';
97 while (t != 0)
99 *p-- = '0' + (t % 10);
100 t /= 10;
103 if (negative)
104 *p-- = '-';
105 return ++p;
109 /* xtoa()-- Integer to hexadecimal conversion. Returns a pointer to a
110 * static buffer. */
112 char *
113 xtoa (GFC_UINTEGER_LARGEST n)
115 int digit;
116 char *p;
118 if (n == 0)
120 buffer[0] = '0';
121 buffer[1] = '\0';
122 return buffer;
125 p = buffer + sizeof (buffer) - 1;
126 *p-- = '\0';
128 while (n != 0)
130 digit = n & 0xF;
131 if (digit > 9)
132 digit += 'A' - '0' - 10;
134 *p-- = '0' + digit;
135 n >>= 4;
138 return ++p;
142 /* st_printf()-- simple printf() function for streams that handles the
143 * formats %d, %s and %c. This function handles printing of error
144 * messages that originate within the library itself, not from a user
145 * program. */
148 st_printf (const char *format, ...)
150 int count, total;
151 va_list arg;
152 char *p, *q;
153 stream *s;
155 total = 0;
156 s = init_error_stream ();
157 va_start (arg, format);
159 for (;;)
161 count = 0;
163 while (format[count] != '%' && format[count] != '\0')
164 count++;
166 if (count != 0)
168 p = salloc_w (s, &count);
169 memmove (p, format, count);
170 sfree (s);
173 total += count;
174 format += count;
175 if (*format++ == '\0')
176 break;
178 switch (*format)
180 case 'c':
181 count = 1;
183 p = salloc_w (s, &count);
184 *p = (char) va_arg (arg, int);
186 sfree (s);
187 break;
189 case 'd':
190 q = gfc_itoa (va_arg (arg, int));
191 count = strlen (q);
193 p = salloc_w (s, &count);
194 memmove (p, q, count);
195 sfree (s);
196 break;
198 case 'x':
199 q = xtoa (va_arg (arg, unsigned));
200 count = strlen (q);
202 p = salloc_w (s, &count);
203 memmove (p, q, count);
204 sfree (s);
205 break;
207 case 's':
208 q = va_arg (arg, char *);
209 count = strlen (q);
211 p = salloc_w (s, &count);
212 memmove (p, q, count);
213 sfree (s);
214 break;
216 case '\0':
217 return total;
219 default:
220 count = 2;
221 p = salloc_w (s, &count);
222 p[0] = format[-1];
223 p[1] = format[0];
224 sfree (s);
225 break;
228 total += count;
229 format++;
232 va_end (arg);
233 return total;
237 /* st_sprintf()-- Simple sprintf() for formatting memory buffers. */
239 void
240 st_sprintf (char *buffer, const char *format, ...)
242 va_list arg;
243 char c, *p;
244 int count;
246 va_start (arg, format);
248 for (;;)
250 c = *format++;
251 if (c != '%')
253 *buffer++ = c;
254 if (c == '\0')
255 break;
256 continue;
259 c = *format++;
260 switch (c)
262 case 'c':
263 *buffer++ = (char) va_arg (arg, int);
264 break;
266 case 'd':
267 p = gfc_itoa (va_arg (arg, int));
268 count = strlen (p);
270 memcpy (buffer, p, count);
271 buffer += count;
272 break;
274 case 's':
275 p = va_arg (arg, char *);
276 count = strlen (p);
278 memcpy (buffer, p, count);
279 buffer += count;
280 break;
282 default:
283 *buffer++ = c;
287 va_end (arg);
291 /* show_locus()-- Print a line number and filename describing where
292 * something went wrong */
294 void
295 show_locus (void)
297 if (!options.locus || filename == NULL)
298 return;
300 st_printf ("At line %d of file %s\n", line, filename);
304 /* recursion_check()-- It's possible for additional errors to occur
305 * during fatal error processing. We detect this condition here and
306 * exit with code 4 immediately. */
308 #define MAGIC 0x20DE8101
310 static void
311 recursion_check (void)
313 static int magic = 0;
315 /* Don't even try to print something at this point */
316 if (magic == MAGIC)
317 sys_exit (4);
319 magic = MAGIC;
323 /* os_error()-- Operating system error. We get a message from the
324 * operating system, show it and leave. Some operating system errors
325 * are caught and processed by the library. If not, we come here. */
327 void
328 os_error (const char *message)
330 recursion_check ();
331 show_locus ();
332 st_printf ("Operating system error: %s\n%s\n", get_oserror (), message);
333 sys_exit (1);
337 /* void runtime_error()-- These are errors associated with an
338 * invalid fortran program. */
340 void
341 runtime_error (const char *message)
343 recursion_check ();
344 show_locus ();
345 st_printf ("Fortran runtime error: %s\n", message);
346 sys_exit (2);
348 iexport(runtime_error);
351 /* void internal_error()-- These are this-can't-happen errors
352 * that indicate something deeply wrong. */
354 void
355 internal_error (const char *message)
357 recursion_check ();
358 show_locus ();
359 st_printf ("Internal Error: %s\n", message);
360 sys_exit (3);
364 /* translate_error()-- Given an integer error code, return a string
365 * describing the error. */
367 const char *
368 translate_error (int code)
370 const char *p;
372 switch (code)
374 case ERROR_EOR:
375 p = "End of record";
376 break;
378 case ERROR_END:
379 p = "End of file";
380 break;
382 case ERROR_OK:
383 p = "Successful return";
384 break;
386 case ERROR_OS:
387 p = "Operating system error";
388 break;
390 case ERROR_BAD_OPTION:
391 p = "Bad statement option";
392 break;
394 case ERROR_MISSING_OPTION:
395 p = "Missing statement option";
396 break;
398 case ERROR_OPTION_CONFLICT:
399 p = "Conflicting statement options";
400 break;
402 case ERROR_ALREADY_OPEN:
403 p = "File already opened in another unit";
404 break;
406 case ERROR_BAD_UNIT:
407 p = "Unattached unit";
408 break;
410 case ERROR_FORMAT:
411 p = "FORMAT error";
412 break;
414 case ERROR_BAD_ACTION:
415 p = "Incorrect ACTION specified";
416 break;
418 case ERROR_ENDFILE:
419 p = "Read past ENDFILE record";
420 break;
422 case ERROR_BAD_US:
423 p = "Corrupt unformatted sequential file";
424 break;
426 case ERROR_READ_VALUE:
427 p = "Bad value during read";
428 break;
430 case ERROR_READ_OVERFLOW:
431 p = "Numeric overflow on read";
432 break;
434 default:
435 p = "Unknown error code";
436 break;
439 return p;
443 /* generate_error()-- Come here when an error happens. This
444 * subroutine is called if it is possible to continue on after the
445 * error. If an IOSTAT variable exists, we set it. If the IOSTAT or
446 * ERR label is present, we return, otherwise we terminate the program
447 * after print a message. The error code is always required but the
448 * message parameter can be NULL, in which case a string describing
449 * the most recent operating system error is used. */
451 void
452 generate_error (int family, const char *message)
454 /* Set the error status. */
455 if (ioparm.iostat != NULL)
456 *ioparm.iostat = family;
458 /* Report status back to the compiler. */
459 switch (family)
461 case ERROR_EOR:
462 ioparm.library_return = LIBRARY_EOR;
463 if (ioparm.eor != 0)
464 return;
465 break;
467 case ERROR_END:
468 ioparm.library_return = LIBRARY_END;
469 if (ioparm.end != 0)
470 return;
471 break;
473 default:
474 ioparm.library_return = LIBRARY_ERROR;
475 if (ioparm.err != 0)
476 return;
477 break;
480 /* Return if the user supplied an iostat variable. */
481 if (ioparm.iostat != NULL)
482 return;
484 /* Terminate the program */
486 if (message == NULL)
487 message =
488 (family == ERROR_OS) ? get_oserror () : translate_error (family);
490 runtime_error (message);