diff options
Diffstat (limited to 'libgfortran/runtime/compile_options.c')
-rw-r--r-- | libgfortran/runtime/compile_options.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c new file mode 100644 index 0000000000..b572c88153 --- /dev/null +++ b/libgfortran/runtime/compile_options.c @@ -0,0 +1,265 @@ +/* Handling of compile-time options that influence the library. + Copyright (C) 2005-2017 Free Software Foundation, Inc. + +This file is part of the GNU Fortran runtime library (libgfortran). + +Libgfortran is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Libgfortran is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#include "libgfortran.h" +#include <signal.h> + + +/* Useful compile-time options will be stored in here. */ +compile_options_t compile_options; + +#ifndef LIBGFOR_MINIMAL +static volatile sig_atomic_t fatal_error_in_progress = 0; + + +/* Helper function for backtrace_handler to write information about the + received signal to stderr before actually giving the backtrace. */ +static void +show_signal (int signum) +{ + const char * name = NULL, * desc = NULL; + + switch (signum) + { +#if defined(SIGQUIT) + case SIGQUIT: + name = "SIGQUIT"; + desc = "Terminal quit signal"; + break; +#endif + + /* The following 4 signals are defined by C89. */ + case SIGILL: + name = "SIGILL"; + desc = "Illegal instruction"; + break; + + case SIGABRT: + name = "SIGABRT"; + desc = "Process abort signal"; + break; + + case SIGFPE: + name = "SIGFPE"; + desc = "Floating-point exception - erroneous arithmetic operation"; + break; + + case SIGSEGV: + name = "SIGSEGV"; + desc = "Segmentation fault - invalid memory reference"; + break; + +#if defined(SIGBUS) + case SIGBUS: + name = "SIGBUS"; + desc = "Access to an undefined portion of a memory object"; + break; +#endif + +#if defined(SIGSYS) + case SIGSYS: + name = "SIGSYS"; + desc = "Bad system call"; + break; +#endif + +#if defined(SIGTRAP) + case SIGTRAP: + name = "SIGTRAP"; + desc = "Trace/breakpoint trap"; + break; +#endif + +#if defined(SIGXCPU) + case SIGXCPU: + name = "SIGXCPU"; + desc = "CPU time limit exceeded"; + break; +#endif + +#if defined(SIGXFSZ) + case SIGXFSZ: + name = "SIGXFSZ"; + desc = "File size limit exceeded"; + break; +#endif + } + + if (name) + st_printf ("\nProgram received signal %s: %s.\n", name, desc); + else + st_printf ("\nProgram received signal %d.\n", signum); +} + + +/* A signal handler to allow us to output a backtrace. */ +void +backtrace_handler (int signum) +{ + /* Since this handler is established for more than one kind of signal, + it might still get invoked recursively by delivery of some other kind + of signal. Use a static variable to keep track of that. */ + if (fatal_error_in_progress) + raise (signum); + fatal_error_in_progress = 1; + + show_signal (signum); + estr_write ("\nBacktrace for this error:\n"); + show_backtrace (true); + + /* Now reraise the signal. We reactivate the signal's + default handling, which is to terminate the process. + We could just call exit or abort, + but reraising the signal sets the return status + from the process correctly. */ + signal (signum, SIG_DFL); + raise (signum); +} +#endif + +/* Set the usual compile-time options. */ +extern void set_options (int , int []); +export_proto(set_options); + +void +set_options (int num, int options[]) +{ + if (num >= 1) + compile_options.warn_std = options[0]; + if (num >= 2) + compile_options.allow_std = options[1]; + if (num >= 3) + compile_options.pedantic = options[2]; + if (num >= 4) + compile_options.backtrace = options[3]; + if (num >= 5) + compile_options.sign_zero = options[4]; + if (num >= 6) + compile_options.bounds_check = options[5]; + if (num >= 7) + compile_options.fpe_summary = options[6]; + +#ifndef LIBGFOR_MINIMAL + /* If backtrace is required, we set signal handlers on the POSIX + 2001 signals with core action. */ + if (compile_options.backtrace) + { +#if defined(SIGQUIT) + signal (SIGQUIT, backtrace_handler); +#endif + + /* The following 4 signals are defined by C89. */ + signal (SIGILL, backtrace_handler); + signal (SIGABRT, backtrace_handler); + signal (SIGFPE, backtrace_handler); + signal (SIGSEGV, backtrace_handler); + +#if defined(SIGBUS) + signal (SIGBUS, backtrace_handler); +#endif + +#if defined(SIGSYS) + signal (SIGSYS, backtrace_handler); +#endif + +#if defined(SIGTRAP) + signal (SIGTRAP, backtrace_handler); +#endif + +#if defined(SIGXCPU) + signal (SIGXCPU, backtrace_handler); +#endif + +#if defined(SIGXFSZ) + signal (SIGXFSZ, backtrace_handler); +#endif + } +#endif +} + + +/* Default values for the compile-time options. Keep in sync with + gcc/fortran/options.c (gfc_init_options). */ +void +init_compile_options (void) +{ + compile_options.warn_std = GFC_STD_F95_DEL | GFC_STD_LEGACY; + compile_options.allow_std = GFC_STD_F95_OBS | GFC_STD_F95_DEL + | GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F95 | GFC_STD_F77 + | GFC_STD_F2008_OBS | GFC_STD_GNU | GFC_STD_LEGACY; + compile_options.pedantic = 0; + compile_options.backtrace = 0; + compile_options.sign_zero = 1; + compile_options.fpe_summary = 0; +} + +/* Function called by the front-end to tell us the + default for unformatted data conversion. */ + +extern void set_convert (int); +export_proto (set_convert); + +void +set_convert (int conv) +{ + compile_options.convert = conv; +} + +extern void set_record_marker (int); +export_proto (set_record_marker); + + +void +set_record_marker (int val) +{ + + switch(val) + { + case 4: + compile_options.record_marker = sizeof (GFC_INTEGER_4); + break; + + case 8: + compile_options.record_marker = sizeof (GFC_INTEGER_8); + break; + + default: + runtime_error ("Invalid value for record marker"); + break; + } +} + +extern void set_max_subrecord_length (int); +export_proto (set_max_subrecord_length); + +void set_max_subrecord_length(int val) +{ + if (val > GFC_MAX_SUBRECORD_LENGTH || val < 1) + { + runtime_error ("Invalid value for maximum subrecord length"); + return; + } + + compile_options.max_subrecord_length = val; +} |