minimal.c revision 1.1.1.4 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