OSDN Git Service

PR 48931 Make backtrace async-signal-safe, reformat output
[pf3gnuchains/gcc-fork.git] / libgfortran / runtime / main.c
index 7720430..54d9e09 100644 (file)
@@ -1,44 +1,49 @@
-/* Copyright (C) 2002-2003, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2003, 2005, 2007, 2009, 2011 
+   Free Software Foundation, Inc.
    Contributed by Andy Vaught and Paul Brook <paul@nowt.org>
 
    Contributed by Andy Vaught and Paul Brook <paul@nowt.org>
 
-This file is part of the GNU Fortran 95 runtime library (libgfortran).
+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
 
 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 any later version.
 
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
 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.
 
 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.
 
-You should have received a copy of the GNU General Public License
-along with libgfortran; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+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 <stdio.h>
+#include "libgfortran.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdlib.h>
 #include <string.h>
-#include <math.h>
-#include <stddef.h>
+#include <limits.h>
 
 
-#include "libgfortran.h"
 
 
-/* This is the offset (in bytes) required to cast from logical(8)* to
-   logical(4)*. and still get the same result.  Will be 0 for little-endian
-   machines and 4 for big-endian machines.  */
-int l8_to_l4_offset = 0;
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Stupid function to be sure the constructor is always linked in, even
+   in the case of static linking.  See PR libfortran/22298 for details.  */
+void
+stupid_function_name_for_static_linking (void)
+{
+  return;
+}
+
+/* This will be 0 for little-endian
+   machines and 1 for big-endian machines.  */
+int big_endian = 0;
 
 
 /* Figure out endianness for this machine.  */
 
 
 /* Figure out endianness for this machine.  */
@@ -54,9 +59,9 @@ determine_endianness (void)
 
   u.l8 = 1;
   if (u.l4[0])
 
   u.l8 = 1;
   if (u.l4[0])
-    l8_to_l4_offset = 0;
+    big_endian = 0;
   else if (u.l4[1])
   else if (u.l4[1])
-    l8_to_l4_offset = 1;
+    big_endian = 1;
   else
     runtime_error ("Unable to determine machine endianness");
 }
   else
     runtime_error ("Unable to determine machine endianness");
 }
@@ -65,6 +70,75 @@ determine_endianness (void)
 static int argc_save;
 static char **argv_save;
 
 static int argc_save;
 static char **argv_save;
 
+static const char *exe_path;
+static int please_free_exe_path_when_done;
+
+/* Save the path under which the program was called, for use in the
+   backtrace routines.  */
+void
+store_exe_path (const char * argv0)
+{
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR   
+#define DIR_SEPARATOR '/'
+#endif
+
+  char buf[PATH_MAX], *cwd, *path;
+
+  /* This can only happen if store_exe_path is called multiple times.  */
+  if (please_free_exe_path_when_done)
+    free ((char *) exe_path);
+
+  /* Reading the /proc/self/exe symlink is Linux-specific(?), but if
+     it works it gives the correct answer.  */
+#ifdef HAVE_READLINK
+  int len;
+  if ((len = readlink ("/proc/self/exe", buf, sizeof (buf) - 1)) != -1)
+    {
+      buf[len] = '\0';
+      exe_path = strdup (buf);
+      please_free_exe_path_when_done = 1;
+      return;
+    }
+#endif
+
+  /* On the simulator argv is not set.  */
+  if (argv0 == NULL || argv0[0] == '/')
+    {
+      exe_path = argv0;
+      please_free_exe_path_when_done = 0;
+      return;
+    }
+
+  memset (buf, 0, sizeof (buf));
+#ifdef HAVE_GETCWD
+  cwd = getcwd (buf, sizeof (buf));
+#else
+  cwd = "";
+#endif
+
+  /* exe_path will be cwd + "/" + argv[0] + "\0".  This will not work
+     if the executable is not in the cwd, but at this point we're out
+     of better ideas.  */
+  size_t pathlen = strlen (cwd) + 1 + strlen (argv0) + 1;
+  path = malloc (pathlen);
+  snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0);
+  exe_path = path;
+  please_free_exe_path_when_done = 1;
+}
+
+
+/* Return the full path of the executable.  */
+char *
+full_exe_path (void)
+{
+  return (char *) exe_path;
+}
+
+
 /* Set the saved values of the command line arguments.  */
 
 void
 /* Set the saved values of the command line arguments.  */
 
 void
@@ -72,7 +146,10 @@ set_args (int argc, char **argv)
 {
   argc_save = argc;
   argv_save = argv;
 {
   argc_save = argc;
   argv_save = argv;
+  store_exe_path (argv[0]);
 }
 }
+iexport(set_args);
+
 
 /* Retrieve the saved values of the command line arguments.  */
 
 
 /* Retrieve the saved values of the command line arguments.  */
 
@@ -96,6 +173,7 @@ init (void)
   init_variables ();
 
   init_units ();
   init_variables ();
 
   init_units ();
+  set_fpu ();
   init_compile_options ();
 
 #ifdef DEBUG
   init_compile_options ();
 
 #ifdef DEBUG
@@ -107,7 +185,7 @@ init (void)
   /* if (argc > 1 && strcmp(argv[1], "--resume") == 0) resume();  */
 #endif
 
   /* if (argc > 1 && strcmp(argv[1], "--resume") == 0) resume();  */
 #endif
 
-  random_seed(NULL,NULL,NULL);
+  random_seed_i4 (NULL, NULL, NULL);
 }
 
 
 }
 
 
@@ -117,4 +195,7 @@ static void __attribute__((destructor))
 cleanup (void)
 {
   close_units ();
 cleanup (void)
 {
   close_units ();
+  
+  if (please_free_exe_path_when_done)
+    free ((char *) exe_path);
 }
 }