xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/runtime/minimal.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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