1*4c3eb207Smrg /* Copyright (C) 2002-2020 Free Software Foundation, Inc.
2627f7eb2Smrg Contributed by Andy Vaught and Paul Brook <paul@nowt.org>
3627f7eb2Smrg
4627f7eb2Smrg This file is part of the GNU Fortran runtime library (libgfortran).
5627f7eb2Smrg
6627f7eb2Smrg Libgfortran is free software; you can redistribute it and/or modify
7627f7eb2Smrg it under the terms of the GNU General Public License as published by
8627f7eb2Smrg the Free Software Foundation; either version 3, or (at your option)
9627f7eb2Smrg any later version.
10627f7eb2Smrg
11627f7eb2Smrg Libgfortran is distributed in the hope that it will be useful,
12627f7eb2Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13627f7eb2Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14627f7eb2Smrg GNU General Public License for more details.
15627f7eb2Smrg
16627f7eb2Smrg Under Section 7 of GPL version 3, you are granted additional
17627f7eb2Smrg permissions described in the GCC Runtime Library Exception, version
18627f7eb2Smrg 3.1, as published by the Free Software Foundation.
19627f7eb2Smrg
20627f7eb2Smrg You should have received a copy of the GNU General Public License and
21627f7eb2Smrg a copy of the GCC Runtime Library Exception along with this program;
22627f7eb2Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23627f7eb2Smrg <http://www.gnu.org/licenses/>. */
24627f7eb2Smrg
25627f7eb2Smrg #include "libgfortran.h"
26627f7eb2Smrg
27*4c3eb207Smrg #include <string.h>
28627f7eb2Smrg
29627f7eb2Smrg #ifdef HAVE_UNISTD_H
30627f7eb2Smrg #include <unistd.h>
31627f7eb2Smrg #endif
32627f7eb2Smrg
33*4c3eb207Smrg
34*4c3eb207Smrg #if __nvptx__
35*4c3eb207Smrg /* Map "exit" to "abort"; see PR85463 '[nvptx] "exit" in offloaded region
36*4c3eb207Smrg doesn't terminate process'. */
37*4c3eb207Smrg # undef exit
38*4c3eb207Smrg # define exit(status) do { (void) (status); abort (); } while (0)
39*4c3eb207Smrg #endif
40*4c3eb207Smrg
41*4c3eb207Smrg
42*4c3eb207Smrg #if __nvptx__
43*4c3eb207Smrg /* 'printf' is all we have. */
44*4c3eb207Smrg # undef estr_vprintf
45*4c3eb207Smrg # define estr_vprintf vprintf
46*4c3eb207Smrg #else
47*4c3eb207Smrg # error TODO
48*4c3eb207Smrg #endif
49*4c3eb207Smrg
50*4c3eb207Smrg
51*4c3eb207Smrg /* runtime/environ.c */
52*4c3eb207Smrg
53*4c3eb207Smrg options_t options;
54*4c3eb207Smrg
55*4c3eb207Smrg
56*4c3eb207Smrg /* runtime/main.c */
57*4c3eb207Smrg
58627f7eb2Smrg /* Stupid function to be sure the constructor is always linked in, even
59627f7eb2Smrg in the case of static linking. See PR libfortran/22298 for details. */
60627f7eb2Smrg void
stupid_function_name_for_static_linking(void)61627f7eb2Smrg stupid_function_name_for_static_linking (void)
62627f7eb2Smrg {
63627f7eb2Smrg return;
64627f7eb2Smrg }
65627f7eb2Smrg
66627f7eb2Smrg
67627f7eb2Smrg static int argc_save;
68627f7eb2Smrg static char **argv_save;
69627f7eb2Smrg
70*4c3eb207Smrg
71*4c3eb207Smrg /* Set the saved values of the command line arguments. */
72*4c3eb207Smrg
73*4c3eb207Smrg void
set_args(int argc,char ** argv)74*4c3eb207Smrg set_args (int argc, char **argv)
75*4c3eb207Smrg {
76*4c3eb207Smrg argc_save = argc;
77*4c3eb207Smrg argv_save = argv;
78*4c3eb207Smrg }
79*4c3eb207Smrg iexport(set_args);
80*4c3eb207Smrg
81*4c3eb207Smrg
82*4c3eb207Smrg /* Retrieve the saved values of the command line arguments. */
83*4c3eb207Smrg
84*4c3eb207Smrg void
get_args(int * argc,char *** argv)85*4c3eb207Smrg get_args (int *argc, char ***argv)
86*4c3eb207Smrg {
87*4c3eb207Smrg *argc = argc_save;
88*4c3eb207Smrg *argv = argv_save;
89*4c3eb207Smrg }
90*4c3eb207Smrg
91*4c3eb207Smrg
92*4c3eb207Smrg /* runtime/error.c */
93*4c3eb207Smrg
94*4c3eb207Smrg /* Write a null-terminated C string to standard error. This function
95*4c3eb207Smrg is async-signal-safe. */
96*4c3eb207Smrg
97*4c3eb207Smrg ssize_t
estr_write(const char * str)98*4c3eb207Smrg estr_write (const char *str)
99*4c3eb207Smrg {
100*4c3eb207Smrg return write (STDERR_FILENO, str, strlen (str));
101*4c3eb207Smrg }
102*4c3eb207Smrg
103*4c3eb207Smrg
104*4c3eb207Smrg /* printf() like function for for printing to stderr. Uses a stack
105*4c3eb207Smrg allocated buffer and doesn't lock stderr, so it should be safe to
106*4c3eb207Smrg use from within a signal handler. */
107*4c3eb207Smrg
108*4c3eb207Smrg int
st_printf(const char * format,...)109*4c3eb207Smrg st_printf (const char * format, ...)
110*4c3eb207Smrg {
111*4c3eb207Smrg int written;
112*4c3eb207Smrg va_list ap;
113*4c3eb207Smrg va_start (ap, format);
114*4c3eb207Smrg written = estr_vprintf (format, ap);
115*4c3eb207Smrg va_end (ap);
116*4c3eb207Smrg return written;
117*4c3eb207Smrg }
118*4c3eb207Smrg
119*4c3eb207Smrg
120*4c3eb207Smrg /* sys_abort()-- Terminate the program showing backtrace and dumping
121*4c3eb207Smrg core. */
122*4c3eb207Smrg
123*4c3eb207Smrg void
sys_abort(void)124*4c3eb207Smrg sys_abort (void)
125*4c3eb207Smrg {
126*4c3eb207Smrg /* If backtracing is enabled, print backtrace and disable signal
127*4c3eb207Smrg handler for ABRT. */
128*4c3eb207Smrg if (options.backtrace == 1
129*4c3eb207Smrg || (options.backtrace == -1 && compile_options.backtrace == 1))
130*4c3eb207Smrg {
131*4c3eb207Smrg estr_write ("\nProgram aborted.\n");
132*4c3eb207Smrg }
133*4c3eb207Smrg
134*4c3eb207Smrg abort();
135*4c3eb207Smrg }
136*4c3eb207Smrg
137*4c3eb207Smrg
138*4c3eb207Smrg /* Exit in case of error termination. If backtracing is enabled, print
139*4c3eb207Smrg backtrace, then exit. */
140*4c3eb207Smrg
141*4c3eb207Smrg void
exit_error(int status)142*4c3eb207Smrg exit_error (int status)
143*4c3eb207Smrg {
144*4c3eb207Smrg if (options.backtrace == 1
145*4c3eb207Smrg || (options.backtrace == -1 && compile_options.backtrace == 1))
146*4c3eb207Smrg {
147*4c3eb207Smrg estr_write ("\nError termination.\n");
148*4c3eb207Smrg }
149*4c3eb207Smrg exit (status);
150*4c3eb207Smrg }
151*4c3eb207Smrg
152*4c3eb207Smrg
153*4c3eb207Smrg /* show_locus()-- Print a line number and filename describing where
154*4c3eb207Smrg * something went wrong */
155*4c3eb207Smrg
156*4c3eb207Smrg void
show_locus(st_parameter_common * cmp)157*4c3eb207Smrg show_locus (st_parameter_common *cmp)
158*4c3eb207Smrg {
159*4c3eb207Smrg char *filename;
160*4c3eb207Smrg
161*4c3eb207Smrg if (!options.locus || cmp == NULL || cmp->filename == NULL)
162*4c3eb207Smrg return;
163*4c3eb207Smrg
164*4c3eb207Smrg if (cmp->unit > 0)
165*4c3eb207Smrg {
166*4c3eb207Smrg filename = /* TODO filename_from_unit (cmp->unit) */ NULL;
167*4c3eb207Smrg
168*4c3eb207Smrg if (filename != NULL)
169*4c3eb207Smrg {
170*4c3eb207Smrg st_printf ("At line %d of file %s (unit = %d, file = '%s')\n",
171*4c3eb207Smrg (int) cmp->line, cmp->filename, (int) cmp->unit, filename);
172*4c3eb207Smrg free (filename);
173*4c3eb207Smrg }
174*4c3eb207Smrg else
175*4c3eb207Smrg {
176*4c3eb207Smrg st_printf ("At line %d of file %s (unit = %d)\n",
177*4c3eb207Smrg (int) cmp->line, cmp->filename, (int) cmp->unit);
178*4c3eb207Smrg }
179*4c3eb207Smrg return;
180*4c3eb207Smrg }
181*4c3eb207Smrg
182*4c3eb207Smrg st_printf ("At line %d of file %s\n", (int) cmp->line, cmp->filename);
183*4c3eb207Smrg }
184*4c3eb207Smrg
185*4c3eb207Smrg
186627f7eb2Smrg /* recursion_check()-- It's possible for additional errors to occur
187627f7eb2Smrg * during fatal error processing. We detect this condition here and
188627f7eb2Smrg * exit with code 4 immediately. */
189627f7eb2Smrg
190627f7eb2Smrg #define MAGIC 0x20DE8101
191627f7eb2Smrg
192627f7eb2Smrg static void
recursion_check(void)193627f7eb2Smrg recursion_check (void)
194627f7eb2Smrg {
195627f7eb2Smrg static int magic = 0;
196627f7eb2Smrg
197627f7eb2Smrg /* Don't even try to print something at this point */
198627f7eb2Smrg if (magic == MAGIC)
199627f7eb2Smrg sys_abort ();
200627f7eb2Smrg
201627f7eb2Smrg magic = MAGIC;
202627f7eb2Smrg }
203627f7eb2Smrg
204627f7eb2Smrg
205627f7eb2Smrg /* os_error()-- Operating system error. We get a message from the
206627f7eb2Smrg * operating system, show it and leave. Some operating system errors
207627f7eb2Smrg * are caught and processed by the library. If not, we come here. */
208627f7eb2Smrg
209627f7eb2Smrg void
os_error(const char * message)210627f7eb2Smrg os_error (const char *message)
211627f7eb2Smrg {
212627f7eb2Smrg recursion_check ();
213*4c3eb207Smrg estr_write ("Operating system error: ");
214*4c3eb207Smrg estr_write (message);
215*4c3eb207Smrg estr_write ("\n");
216*4c3eb207Smrg exit_error (1);
217627f7eb2Smrg }
218*4c3eb207Smrg iexport(os_error); /* TODO, DEPRECATED, ABI: Should not be exported
219*4c3eb207Smrg anymore when bumping so version. */
220*4c3eb207Smrg
221*4c3eb207Smrg
222*4c3eb207Smrg /* Improved version of os_error with a printf style format string and
223*4c3eb207Smrg a locus. */
224*4c3eb207Smrg
225*4c3eb207Smrg void
os_error_at(const char * where,const char * message,...)226*4c3eb207Smrg os_error_at (const char *where, const char *message, ...)
227*4c3eb207Smrg {
228*4c3eb207Smrg va_list ap;
229*4c3eb207Smrg
230*4c3eb207Smrg recursion_check ();
231*4c3eb207Smrg estr_write (where);
232*4c3eb207Smrg estr_write (": ");
233*4c3eb207Smrg va_start (ap, message);
234*4c3eb207Smrg estr_vprintf (message, ap);
235*4c3eb207Smrg va_end (ap);
236*4c3eb207Smrg estr_write ("\n");
237*4c3eb207Smrg exit_error (1);
238*4c3eb207Smrg }
239*4c3eb207Smrg iexport(os_error_at);
240627f7eb2Smrg
241627f7eb2Smrg
242627f7eb2Smrg /* void runtime_error()-- These are errors associated with an
243627f7eb2Smrg * invalid fortran program. */
244627f7eb2Smrg
245627f7eb2Smrg void
runtime_error(const char * message,...)246627f7eb2Smrg runtime_error (const char *message, ...)
247627f7eb2Smrg {
248627f7eb2Smrg va_list ap;
249627f7eb2Smrg
250627f7eb2Smrg recursion_check ();
251*4c3eb207Smrg estr_write ("Fortran runtime error: ");
252627f7eb2Smrg va_start (ap, message);
253*4c3eb207Smrg estr_vprintf (message, ap);
254627f7eb2Smrg va_end (ap);
255*4c3eb207Smrg estr_write ("\n");
256*4c3eb207Smrg exit_error (2);
257627f7eb2Smrg }
258627f7eb2Smrg iexport(runtime_error);
259627f7eb2Smrg
260627f7eb2Smrg /* void runtime_error_at()-- These are errors associated with a
261627f7eb2Smrg * run time error generated by the front end compiler. */
262627f7eb2Smrg
263627f7eb2Smrg void
runtime_error_at(const char * where,const char * message,...)264627f7eb2Smrg runtime_error_at (const char *where, const char *message, ...)
265627f7eb2Smrg {
266627f7eb2Smrg va_list ap;
267627f7eb2Smrg
268627f7eb2Smrg recursion_check ();
269*4c3eb207Smrg estr_write (where);
270*4c3eb207Smrg estr_write ("\nFortran runtime error: ");
271627f7eb2Smrg va_start (ap, message);
272*4c3eb207Smrg estr_vprintf (message, ap);
273627f7eb2Smrg va_end (ap);
274*4c3eb207Smrg estr_write ("\n");
275*4c3eb207Smrg exit_error (2);
276627f7eb2Smrg }
277627f7eb2Smrg iexport(runtime_error_at);
278627f7eb2Smrg
279627f7eb2Smrg
280627f7eb2Smrg void
runtime_warning_at(const char * where,const char * message,...)281627f7eb2Smrg runtime_warning_at (const char *where, const char *message, ...)
282627f7eb2Smrg {
283627f7eb2Smrg va_list ap;
284627f7eb2Smrg
285*4c3eb207Smrg estr_write (where);
286*4c3eb207Smrg estr_write ("\nFortran runtime warning: ");
287627f7eb2Smrg va_start (ap, message);
288*4c3eb207Smrg estr_vprintf (message, ap);
289627f7eb2Smrg va_end (ap);
290*4c3eb207Smrg estr_write ("\n");
291627f7eb2Smrg }
292627f7eb2Smrg iexport(runtime_warning_at);
293627f7eb2Smrg
294627f7eb2Smrg
295627f7eb2Smrg /* void internal_error()-- These are this-can't-happen errors
296627f7eb2Smrg * that indicate something deeply wrong. */
297627f7eb2Smrg
298627f7eb2Smrg void
internal_error(st_parameter_common * cmp,const char * message)299627f7eb2Smrg internal_error (st_parameter_common *cmp, const char *message)
300627f7eb2Smrg {
301627f7eb2Smrg recursion_check ();
302*4c3eb207Smrg show_locus (cmp);
303*4c3eb207Smrg estr_write ("Internal Error: ");
304*4c3eb207Smrg estr_write (message);
305*4c3eb207Smrg estr_write ("\n");
306627f7eb2Smrg
307627f7eb2Smrg /* This function call is here to get the main.o object file included
308627f7eb2Smrg when linking statically. This works because error.o is supposed to
309627f7eb2Smrg be always linked in (and the function call is in internal_error
310627f7eb2Smrg because hopefully it doesn't happen too often). */
311627f7eb2Smrg stupid_function_name_for_static_linking();
312627f7eb2Smrg
313*4c3eb207Smrg exit_error (3);
314627f7eb2Smrg }
315627f7eb2Smrg
316627f7eb2Smrg
317627f7eb2Smrg /* runtime/stop.c */
318627f7eb2Smrg
319627f7eb2Smrg #undef report_exception
320627f7eb2Smrg #define report_exception() do {} while (0)
321*4c3eb207Smrg
322627f7eb2Smrg
323627f7eb2Smrg /* A numeric STOP statement. */
324627f7eb2Smrg
325627f7eb2Smrg extern _Noreturn void stop_numeric (int, bool);
326627f7eb2Smrg export_proto(stop_numeric);
327627f7eb2Smrg
328627f7eb2Smrg void
stop_numeric(int code,bool quiet)329627f7eb2Smrg stop_numeric (int code, bool quiet)
330627f7eb2Smrg {
331627f7eb2Smrg if (!quiet)
332627f7eb2Smrg {
333627f7eb2Smrg report_exception ();
334627f7eb2Smrg st_printf ("STOP %d\n", code);
335627f7eb2Smrg }
336627f7eb2Smrg exit (code);
337627f7eb2Smrg }
338627f7eb2Smrg
339627f7eb2Smrg
340627f7eb2Smrg /* A character string or blank STOP statement. */
341627f7eb2Smrg
342627f7eb2Smrg void
stop_string(const char * string,size_t len,bool quiet)343627f7eb2Smrg stop_string (const char *string, size_t len, bool quiet)
344627f7eb2Smrg {
345627f7eb2Smrg if (!quiet)
346627f7eb2Smrg {
347627f7eb2Smrg report_exception ();
348627f7eb2Smrg if (string)
349627f7eb2Smrg {
350627f7eb2Smrg estr_write ("STOP ");
351627f7eb2Smrg (void) write (STDERR_FILENO, string, len);
352627f7eb2Smrg estr_write ("\n");
353627f7eb2Smrg }
354627f7eb2Smrg }
355627f7eb2Smrg exit (0);
356627f7eb2Smrg }
357627f7eb2Smrg
358627f7eb2Smrg
359627f7eb2Smrg /* Per Fortran 2008, section 8.4: "Execution of a STOP statement initiates
360627f7eb2Smrg normal termination of execution. Execution of an ERROR STOP statement
361627f7eb2Smrg initiates error termination of execution." Thus, error_stop_string returns
362627f7eb2Smrg a nonzero exit status code. */
363627f7eb2Smrg
364627f7eb2Smrg extern _Noreturn void error_stop_string (const char *, size_t, bool);
365627f7eb2Smrg export_proto(error_stop_string);
366627f7eb2Smrg
367627f7eb2Smrg void
error_stop_string(const char * string,size_t len,bool quiet)368627f7eb2Smrg error_stop_string (const char *string, size_t len, bool quiet)
369627f7eb2Smrg {
370627f7eb2Smrg if (!quiet)
371627f7eb2Smrg {
372627f7eb2Smrg report_exception ();
373627f7eb2Smrg estr_write ("ERROR STOP ");
374627f7eb2Smrg (void) write (STDERR_FILENO, string, len);
375627f7eb2Smrg estr_write ("\n");
376627f7eb2Smrg }
377627f7eb2Smrg exit_error (1);
378627f7eb2Smrg }
379627f7eb2Smrg
380627f7eb2Smrg
381627f7eb2Smrg /* A numeric ERROR STOP statement. */
382627f7eb2Smrg
383627f7eb2Smrg extern _Noreturn void error_stop_numeric (int, bool);
384627f7eb2Smrg export_proto(error_stop_numeric);
385627f7eb2Smrg
386627f7eb2Smrg void
error_stop_numeric(int code,bool quiet)387627f7eb2Smrg error_stop_numeric (int code, bool quiet)
388627f7eb2Smrg {
389627f7eb2Smrg if (!quiet)
390627f7eb2Smrg {
391627f7eb2Smrg report_exception ();
392627f7eb2Smrg st_printf ("ERROR STOP %d\n", code);
393627f7eb2Smrg }
394627f7eb2Smrg exit_error (code);
395627f7eb2Smrg }
396