Home | History | Annotate | Line # | Download | only in runtime
      1  1.1.1.4  mrg /* Copyright (C) 2002-2024 Free Software Foundation, Inc.
      2      1.1  mrg    Contributed by Andy Vaught and Paul Brook <paul (at) nowt.org>
      3      1.1  mrg 
      4      1.1  mrg This file is part of the GNU Fortran runtime library (libgfortran).
      5      1.1  mrg 
      6      1.1  mrg Libgfortran is free software; you can redistribute it and/or modify
      7      1.1  mrg it under the terms of the GNU General Public License as published by
      8      1.1  mrg the Free Software Foundation; either version 3, or (at your option)
      9      1.1  mrg any later version.
     10      1.1  mrg 
     11      1.1  mrg Libgfortran is distributed in the hope that it will be useful,
     12      1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      1.1  mrg GNU General Public License for more details.
     15      1.1  mrg 
     16      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     17      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     18      1.1  mrg 3.1, as published by the Free Software Foundation.
     19      1.1  mrg 
     20      1.1  mrg You should have received a copy of the GNU General Public License and
     21      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     22      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23      1.1  mrg <http://www.gnu.org/licenses/>.  */
     24      1.1  mrg 
     25      1.1  mrg #include "libgfortran.h"
     26      1.1  mrg 
     27  1.1.1.2  mrg #include <string.h>
     28      1.1  mrg 
     29      1.1  mrg #ifdef HAVE_UNISTD_H
     30      1.1  mrg #include <unistd.h>
     31      1.1  mrg #endif
     32      1.1  mrg 
     33  1.1.1.2  mrg 
     34  1.1.1.2  mrg #if __nvptx__
     35  1.1.1.2  mrg /* Map "exit" to "abort"; see PR85463 '[nvptx] "exit" in offloaded region
     36  1.1.1.2  mrg    doesn't terminate process'.  */
     37  1.1.1.2  mrg # undef exit
     38  1.1.1.2  mrg # define exit(status) do { (void) (status); abort (); } while (0)
     39  1.1.1.2  mrg #endif
     40  1.1.1.2  mrg 
     41  1.1.1.2  mrg 
     42  1.1.1.2  mrg #if __nvptx__
     43  1.1.1.2  mrg /* 'printf' is all we have.  */
     44  1.1.1.2  mrg # undef estr_vprintf
     45  1.1.1.2  mrg # define estr_vprintf vprintf
     46  1.1.1.2  mrg #else
     47  1.1.1.2  mrg # error TODO
     48  1.1.1.2  mrg #endif
     49  1.1.1.2  mrg 
     50  1.1.1.2  mrg 
     51  1.1.1.2  mrg /* runtime/environ.c */
     52  1.1.1.2  mrg 
     53  1.1.1.2  mrg options_t options;
     54  1.1.1.2  mrg 
     55  1.1.1.2  mrg 
     56  1.1.1.2  mrg /* runtime/main.c */
     57  1.1.1.2  mrg 
     58      1.1  mrg /* Stupid function to be sure the constructor is always linked in, even
     59      1.1  mrg    in the case of static linking.  See PR libfortran/22298 for details.  */
     60      1.1  mrg void
     61      1.1  mrg stupid_function_name_for_static_linking (void)
     62      1.1  mrg {
     63      1.1  mrg   return;
     64      1.1  mrg }
     65      1.1  mrg 
     66      1.1  mrg 
     67      1.1  mrg static int argc_save;
     68      1.1  mrg static char **argv_save;
     69      1.1  mrg 
     70  1.1.1.2  mrg 
     71  1.1.1.2  mrg /* Set the saved values of the command line arguments.  */
     72  1.1.1.2  mrg 
     73  1.1.1.2  mrg void
     74  1.1.1.2  mrg set_args (int argc, char **argv)
     75  1.1.1.2  mrg {
     76  1.1.1.2  mrg   argc_save = argc;
     77  1.1.1.2  mrg   argv_save = argv;
     78  1.1.1.2  mrg }
     79  1.1.1.2  mrg iexport(set_args);
     80  1.1.1.2  mrg 
     81  1.1.1.2  mrg 
     82  1.1.1.2  mrg /* Retrieve the saved values of the command line arguments.  */
     83  1.1.1.2  mrg 
     84  1.1.1.2  mrg void
     85  1.1.1.2  mrg get_args (int *argc, char ***argv)
     86  1.1.1.2  mrg {
     87  1.1.1.2  mrg   *argc = argc_save;
     88  1.1.1.2  mrg   *argv = argv_save;
     89  1.1.1.2  mrg }
     90  1.1.1.2  mrg 
     91  1.1.1.2  mrg 
     92  1.1.1.2  mrg /* runtime/error.c */
     93  1.1.1.2  mrg 
     94  1.1.1.2  mrg /* Write a null-terminated C string to standard error. This function
     95  1.1.1.2  mrg    is async-signal-safe.  */
     96  1.1.1.2  mrg 
     97  1.1.1.2  mrg ssize_t
     98  1.1.1.2  mrg estr_write (const char *str)
     99  1.1.1.2  mrg {
    100  1.1.1.2  mrg   return write (STDERR_FILENO, str, strlen (str));
    101  1.1.1.2  mrg }
    102  1.1.1.2  mrg 
    103  1.1.1.2  mrg 
    104  1.1.1.2  mrg /* printf() like function for for printing to stderr.  Uses a stack
    105  1.1.1.2  mrg    allocated buffer and doesn't lock stderr, so it should be safe to
    106  1.1.1.2  mrg    use from within a signal handler.  */
    107  1.1.1.2  mrg 
    108  1.1.1.2  mrg int
    109  1.1.1.2  mrg st_printf (const char * format, ...)
    110  1.1.1.2  mrg {
    111  1.1.1.2  mrg   int written;
    112  1.1.1.2  mrg   va_list ap;
    113  1.1.1.2  mrg   va_start (ap, format);
    114  1.1.1.2  mrg   written = estr_vprintf (format, ap);
    115  1.1.1.2  mrg   va_end (ap);
    116  1.1.1.2  mrg   return written;
    117  1.1.1.2  mrg }
    118  1.1.1.2  mrg 
    119  1.1.1.2  mrg 
    120  1.1.1.2  mrg /* sys_abort()-- Terminate the program showing backtrace and dumping
    121  1.1.1.2  mrg    core.  */
    122  1.1.1.2  mrg 
    123  1.1.1.2  mrg void
    124  1.1.1.2  mrg sys_abort (void)
    125  1.1.1.2  mrg {
    126  1.1.1.2  mrg   /* If backtracing is enabled, print backtrace and disable signal
    127  1.1.1.2  mrg      handler for ABRT.  */
    128  1.1.1.2  mrg   if (options.backtrace == 1
    129  1.1.1.2  mrg       || (options.backtrace == -1 && compile_options.backtrace == 1))
    130  1.1.1.2  mrg     {
    131  1.1.1.2  mrg       estr_write ("\nProgram aborted.\n");
    132  1.1.1.2  mrg     }
    133  1.1.1.2  mrg 
    134  1.1.1.2  mrg   abort();
    135  1.1.1.2  mrg }
    136  1.1.1.2  mrg 
    137  1.1.1.2  mrg 
    138  1.1.1.2  mrg /* Exit in case of error termination. If backtracing is enabled, print
    139  1.1.1.2  mrg    backtrace, then exit.  */
    140  1.1.1.2  mrg 
    141  1.1.1.2  mrg void
    142  1.1.1.2  mrg exit_error (int status)
    143  1.1.1.2  mrg {
    144  1.1.1.2  mrg   if (options.backtrace == 1
    145  1.1.1.2  mrg       || (options.backtrace == -1 && compile_options.backtrace == 1))
    146  1.1.1.2  mrg     {
    147  1.1.1.2  mrg       estr_write ("\nError termination.\n");
    148  1.1.1.2  mrg     }
    149  1.1.1.2  mrg   exit (status);
    150  1.1.1.2  mrg }
    151  1.1.1.2  mrg 
    152  1.1.1.2  mrg 
    153  1.1.1.2  mrg /* show_locus()-- Print a line number and filename describing where
    154  1.1.1.2  mrg  * something went wrong */
    155  1.1.1.2  mrg 
    156  1.1.1.2  mrg void
    157  1.1.1.2  mrg show_locus (st_parameter_common *cmp)
    158  1.1.1.2  mrg {
    159  1.1.1.2  mrg   char *filename;
    160  1.1.1.2  mrg 
    161  1.1.1.2  mrg   if (!options.locus || cmp == NULL || cmp->filename == NULL)
    162  1.1.1.2  mrg     return;
    163  1.1.1.2  mrg 
    164  1.1.1.2  mrg   if (cmp->unit > 0)
    165  1.1.1.2  mrg     {
    166  1.1.1.2  mrg       filename = /* TODO filename_from_unit (cmp->unit) */ NULL;
    167  1.1.1.2  mrg 
    168  1.1.1.2  mrg       if (filename != NULL)
    169  1.1.1.2  mrg 	{
    170  1.1.1.2  mrg 	  st_printf ("At line %d of file %s (unit = %d, file = '%s')\n",
    171  1.1.1.2  mrg 		   (int) cmp->line, cmp->filename, (int) cmp->unit, filename);
    172  1.1.1.2  mrg 	  free (filename);
    173  1.1.1.2  mrg 	}
    174  1.1.1.2  mrg       else
    175  1.1.1.2  mrg 	{
    176  1.1.1.2  mrg 	  st_printf ("At line %d of file %s (unit = %d)\n",
    177  1.1.1.2  mrg 		   (int) cmp->line, cmp->filename, (int) cmp->unit);
    178  1.1.1.2  mrg 	}
    179  1.1.1.2  mrg       return;
    180  1.1.1.2  mrg     }
    181  1.1.1.2  mrg 
    182  1.1.1.2  mrg   st_printf ("At line %d of file %s\n", (int) cmp->line, cmp->filename);
    183  1.1.1.2  mrg }
    184  1.1.1.2  mrg 
    185  1.1.1.2  mrg 
    186      1.1  mrg /* recursion_check()-- It's possible for additional errors to occur
    187      1.1  mrg  * during fatal error processing.  We detect this condition here and
    188      1.1  mrg  * exit with code 4 immediately. */
    189      1.1  mrg 
    190      1.1  mrg #define MAGIC 0x20DE8101
    191      1.1  mrg 
    192      1.1  mrg static void
    193      1.1  mrg recursion_check (void)
    194      1.1  mrg {
    195      1.1  mrg   static int magic = 0;
    196      1.1  mrg 
    197      1.1  mrg   /* Don't even try to print something at this point */
    198      1.1  mrg   if (magic == MAGIC)
    199      1.1  mrg     sys_abort ();
    200      1.1  mrg 
    201      1.1  mrg   magic = MAGIC;
    202      1.1  mrg }
    203      1.1  mrg 
    204      1.1  mrg 
    205      1.1  mrg /* os_error()-- Operating system error.  We get a message from the
    206      1.1  mrg  * operating system, show it and leave.  Some operating system errors
    207      1.1  mrg  * are caught and processed by the library.  If not, we come here. */
    208      1.1  mrg 
    209      1.1  mrg void
    210      1.1  mrg os_error (const char *message)
    211      1.1  mrg {
    212      1.1  mrg   recursion_check ();
    213  1.1.1.2  mrg   estr_write ("Operating system error: ");
    214  1.1.1.2  mrg   estr_write (message);
    215  1.1.1.2  mrg   estr_write ("\n");
    216  1.1.1.2  mrg   exit_error (1);
    217      1.1  mrg }
    218  1.1.1.2  mrg iexport(os_error); /* TODO, DEPRECATED, ABI: Should not be exported
    219  1.1.1.2  mrg 		      anymore when bumping so version.  */
    220  1.1.1.2  mrg 
    221  1.1.1.2  mrg 
    222  1.1.1.2  mrg /* Improved version of os_error with a printf style format string and
    223  1.1.1.2  mrg    a locus.  */
    224  1.1.1.2  mrg 
    225  1.1.1.2  mrg void
    226  1.1.1.2  mrg os_error_at (const char *where, const char *message, ...)
    227  1.1.1.2  mrg {
    228  1.1.1.2  mrg   va_list ap;
    229  1.1.1.2  mrg 
    230  1.1.1.2  mrg   recursion_check ();
    231  1.1.1.2  mrg   estr_write (where);
    232  1.1.1.2  mrg   estr_write (": ");
    233  1.1.1.2  mrg   va_start (ap, message);
    234  1.1.1.2  mrg   estr_vprintf (message, ap);
    235  1.1.1.2  mrg   va_end (ap);
    236  1.1.1.2  mrg   estr_write ("\n");
    237  1.1.1.2  mrg   exit_error (1);
    238  1.1.1.2  mrg }
    239  1.1.1.2  mrg iexport(os_error_at);
    240      1.1  mrg 
    241      1.1  mrg 
    242      1.1  mrg /* void runtime_error()-- These are errors associated with an
    243      1.1  mrg  * invalid fortran program. */
    244      1.1  mrg 
    245      1.1  mrg void
    246      1.1  mrg runtime_error (const char *message, ...)
    247      1.1  mrg {
    248      1.1  mrg   va_list ap;
    249      1.1  mrg 
    250      1.1  mrg   recursion_check ();
    251  1.1.1.2  mrg   estr_write ("Fortran runtime error: ");
    252      1.1  mrg   va_start (ap, message);
    253  1.1.1.2  mrg   estr_vprintf (message, ap);
    254      1.1  mrg   va_end (ap);
    255  1.1.1.2  mrg   estr_write ("\n");
    256  1.1.1.2  mrg   exit_error (2);
    257      1.1  mrg }
    258      1.1  mrg iexport(runtime_error);
    259      1.1  mrg 
    260      1.1  mrg /* void runtime_error_at()-- These are errors associated with a
    261      1.1  mrg  * run time error generated by the front end compiler.  */
    262      1.1  mrg 
    263      1.1  mrg void
    264      1.1  mrg runtime_error_at (const char *where, const char *message, ...)
    265      1.1  mrg {
    266      1.1  mrg   va_list ap;
    267      1.1  mrg 
    268      1.1  mrg   recursion_check ();
    269  1.1.1.2  mrg   estr_write (where);
    270  1.1.1.2  mrg   estr_write ("\nFortran runtime error: ");
    271      1.1  mrg   va_start (ap, message);
    272  1.1.1.2  mrg   estr_vprintf (message, ap);
    273      1.1  mrg   va_end (ap);
    274  1.1.1.2  mrg   estr_write ("\n");
    275  1.1.1.2  mrg   exit_error (2);
    276      1.1  mrg }
    277      1.1  mrg iexport(runtime_error_at);
    278      1.1  mrg 
    279      1.1  mrg 
    280      1.1  mrg void
    281      1.1  mrg runtime_warning_at (const char *where, const char *message, ...)
    282      1.1  mrg {
    283      1.1  mrg   va_list ap;
    284      1.1  mrg 
    285  1.1.1.2  mrg   estr_write (where);
    286  1.1.1.2  mrg   estr_write ("\nFortran runtime warning: ");
    287      1.1  mrg   va_start (ap, message);
    288  1.1.1.2  mrg   estr_vprintf (message, ap);
    289      1.1  mrg   va_end (ap);
    290  1.1.1.2  mrg   estr_write ("\n");
    291      1.1  mrg }
    292      1.1  mrg iexport(runtime_warning_at);
    293      1.1  mrg 
    294      1.1  mrg 
    295      1.1  mrg /* void internal_error()-- These are this-can't-happen errors
    296      1.1  mrg  * that indicate something deeply wrong. */
    297      1.1  mrg 
    298      1.1  mrg void
    299      1.1  mrg internal_error (st_parameter_common *cmp, const char *message)
    300      1.1  mrg {
    301      1.1  mrg   recursion_check ();
    302  1.1.1.2  mrg   show_locus (cmp);
    303  1.1.1.2  mrg   estr_write ("Internal Error: ");
    304  1.1.1.2  mrg   estr_write (message);
    305  1.1.1.2  mrg   estr_write ("\n");
    306      1.1  mrg 
    307      1.1  mrg   /* This function call is here to get the main.o object file included
    308      1.1  mrg      when linking statically. This works because error.o is supposed to
    309      1.1  mrg      be always linked in (and the function call is in internal_error
    310      1.1  mrg      because hopefully it doesn't happen too often).  */
    311      1.1  mrg   stupid_function_name_for_static_linking();
    312      1.1  mrg 
    313  1.1.1.2  mrg   exit_error (3);
    314      1.1  mrg }
    315      1.1  mrg 
    316      1.1  mrg 
    317      1.1  mrg /* runtime/stop.c */
    318      1.1  mrg 
    319      1.1  mrg #undef report_exception
    320      1.1  mrg #define report_exception() do {} while (0)
    321  1.1.1.2  mrg 
    322      1.1  mrg 
    323      1.1  mrg /* A numeric STOP statement.  */
    324      1.1  mrg 
    325      1.1  mrg extern _Noreturn void stop_numeric (int, bool);
    326      1.1  mrg export_proto(stop_numeric);
    327      1.1  mrg 
    328      1.1  mrg void
    329      1.1  mrg stop_numeric (int code, bool quiet)
    330      1.1  mrg {
    331      1.1  mrg   if (!quiet)
    332      1.1  mrg     {
    333      1.1  mrg       report_exception ();
    334      1.1  mrg       st_printf ("STOP %d\n", code);
    335      1.1  mrg     }
    336      1.1  mrg   exit (code);
    337      1.1  mrg }
    338      1.1  mrg 
    339      1.1  mrg 
    340      1.1  mrg /* A character string or blank STOP statement.  */
    341      1.1  mrg 
    342      1.1  mrg void
    343      1.1  mrg stop_string (const char *string, size_t len, bool quiet)
    344      1.1  mrg {
    345      1.1  mrg   if (!quiet)
    346      1.1  mrg     {
    347      1.1  mrg       report_exception ();
    348      1.1  mrg       if (string)
    349      1.1  mrg 	{
    350      1.1  mrg 	  estr_write ("STOP ");
    351      1.1  mrg 	  (void) write (STDERR_FILENO, string, len);
    352      1.1  mrg 	  estr_write ("\n");
    353      1.1  mrg 	}
    354      1.1  mrg     }
    355      1.1  mrg   exit (0);
    356      1.1  mrg }
    357      1.1  mrg 
    358      1.1  mrg 
    359      1.1  mrg /* Per Fortran 2008, section 8.4:  "Execution of a STOP statement initiates
    360      1.1  mrg    normal termination of execution. Execution of an ERROR STOP statement
    361      1.1  mrg    initiates error termination of execution."  Thus, error_stop_string returns
    362      1.1  mrg    a nonzero exit status code.  */
    363      1.1  mrg 
    364      1.1  mrg extern _Noreturn void error_stop_string (const char *, size_t, bool);
    365      1.1  mrg export_proto(error_stop_string);
    366      1.1  mrg 
    367      1.1  mrg void
    368      1.1  mrg error_stop_string (const char *string, size_t len, bool quiet)
    369      1.1  mrg {
    370      1.1  mrg   if (!quiet)
    371      1.1  mrg     {
    372      1.1  mrg       report_exception ();
    373      1.1  mrg       estr_write ("ERROR STOP ");
    374      1.1  mrg       (void) write (STDERR_FILENO, string, len);
    375      1.1  mrg       estr_write ("\n");
    376      1.1  mrg     }
    377      1.1  mrg   exit_error (1);
    378      1.1  mrg }
    379      1.1  mrg 
    380      1.1  mrg 
    381      1.1  mrg /* A numeric ERROR STOP statement.  */
    382      1.1  mrg 
    383      1.1  mrg extern _Noreturn void error_stop_numeric (int, bool);
    384      1.1  mrg export_proto(error_stop_numeric);
    385      1.1  mrg 
    386      1.1  mrg void
    387      1.1  mrg error_stop_numeric (int code, bool quiet)
    388      1.1  mrg {
    389      1.1  mrg   if (!quiet)
    390      1.1  mrg     {
    391      1.1  mrg       report_exception ();
    392      1.1  mrg       st_printf ("ERROR STOP %d\n", code);
    393      1.1  mrg     }
    394      1.1  mrg   exit_error (code);
    395      1.1  mrg }
    396