summaryrefslogtreecommitdiff
path: root/libgfortran/runtime
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-04-22 10:21:45 +0000
committer <>2015-04-25 21:44:09 +0000
commitf80b5ea1605c9f9408c5aa386ba71c16d918ebbf (patch)
treebb7eafaa81fc4b8c5c215bc08d517fd158db234a /libgfortran/runtime
parentc27a97d04853380f1e80525391b3f0d156ed4c84 (diff)
downloadgcc-tarball-f80b5ea1605c9f9408c5aa386ba71c16d918ebbf.tar.gz
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-5.1.0.tar.bz2.gcc-5.1.0
Diffstat (limited to 'libgfortran/runtime')
-rw-r--r--libgfortran/runtime/backtrace.c2
-rw-r--r--libgfortran/runtime/bounds.c2
-rw-r--r--libgfortran/runtime/compile_options.c7
-rw-r--r--libgfortran/runtime/convert_char.c2
-rw-r--r--libgfortran/runtime/environ.c2
-rw-r--r--libgfortran/runtime/error.c29
-rw-r--r--libgfortran/runtime/fpu.c2
-rw-r--r--libgfortran/runtime/in_pack_generic.c2
-rw-r--r--libgfortran/runtime/in_unpack_generic.c2
-rw-r--r--libgfortran/runtime/main.c66
-rw-r--r--libgfortran/runtime/memory.c16
-rw-r--r--libgfortran/runtime/minimal.c210
-rw-r--r--libgfortran/runtime/pause.c2
-rw-r--r--libgfortran/runtime/select.c2
-rw-r--r--libgfortran/runtime/select_inc.c2
-rw-r--r--libgfortran/runtime/stop.c14
-rw-r--r--libgfortran/runtime/string.c60
17 files changed, 377 insertions, 45 deletions
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 9cc6974ee1..317da1f493 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2006-2015 Free Software Foundation, Inc.
Contributed by François-Xavier Coudert
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/bounds.c b/libgfortran/runtime/bounds.c
index 2544cb6620..c324d44367 100644
--- a/libgfortran/runtime/bounds.c
+++ b/libgfortran/runtime/bounds.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
Contributed by Thomas Koenig
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c
index 748ac23354..98f67f0705 100644
--- a/libgfortran/runtime/compile_options.c
+++ b/libgfortran/runtime/compile_options.c
@@ -1,5 +1,5 @@
/* Handling of compile-time options that influence the library.
- Copyright (C) 2005-2014 Free Software Foundation, Inc.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -29,7 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Useful compile-time options will be stored in here. */
compile_options_t compile_options;
-
+#ifndef LIBGFOR_MINIMAL
volatile sig_atomic_t fatal_error_in_progress = 0;
@@ -146,6 +146,7 @@ maybe_find_addr2line (void)
if (options.backtrace == -1)
find_addr2line ();
}
+#endif
/* Set the usual compile-time options. */
extern void set_options (int , int []);
@@ -176,6 +177,7 @@ set_options (int num, int options[])
if (num >= 9)
compile_options.fpe_summary = options[8];
+#ifndef LIBGFOR_MINIMAL
/* If backtrace is required, we set signal handlers on the POSIX
2001 signals with core action. */
if (compile_options.backtrace)
@@ -212,6 +214,7 @@ set_options (int num, int options[])
maybe_find_addr2line ();
}
+#endif
}
diff --git a/libgfortran/runtime/convert_char.c b/libgfortran/runtime/convert_char.c
index c3cd1c28c1..0c5db3cf19 100644
--- a/libgfortran/runtime/convert_char.c
+++ b/libgfortran/runtime/convert_char.c
@@ -1,5 +1,5 @@
/* Runtime conversion of strings from one character kind to another.
- Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/environ.c b/libgfortran/runtime/environ.c
index 1095f443a5..4f6408f8ef 100644
--- a/libgfortran/runtime/environ.c
+++ b/libgfortran/runtime/environ.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Andy Vaught
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index 4bde33ba72..098231916a 100644
--- a/libgfortran/runtime/error.c
+++ b/libgfortran/runtime/error.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Andy Vaught
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -46,6 +46,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
+#include <locale.h>
+
+#ifdef HAVE_XLOCALE_H
+#include <xlocale.h>
+#endif
+
+
#ifdef __MINGW32__
#define HAVE_GETPID 1
#include <process.h>
@@ -204,14 +211,26 @@ gfc_xtoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
}
-/* Hopefully thread-safe wrapper for a strerror_r() style function. */
+/* Hopefully thread-safe wrapper for a strerror() style function. */
char *
gf_strerror (int errnum,
char * buf __attribute__((unused)),
size_t buflen __attribute__((unused)))
{
-#ifdef HAVE_STRERROR_R
+#ifdef HAVE_STRERROR_L
+ locale_t myloc = newlocale (LC_CTYPE_MASK | LC_MESSAGES_MASK, "",
+ (locale_t) 0);
+ char *p = strerror_l (errnum, myloc);
+ freelocale (myloc);
+ return p;
+#elif defined(HAVE_STRERROR_R)
+#ifdef HAVE_USELOCALE
+ /* Some targets (Darwin at least) have the POSIX 2008 extended
+ locale functions, but not strerror_l. So reset the per-thread
+ locale here. */
+ uselocale (LC_GLOBAL_LOCALE);
+#endif
/* POSIX returns an "int", GNU a "char*". */
return
__builtin_choose_expr (__builtin_classify_type (strerror_r (0, buf, 0))
@@ -469,6 +488,10 @@ translate_error (int code)
p = "Unformatted file structure has been corrupted";
break;
+ case LIBERROR_INQUIRE_INTERNAL_UNIT:
+ p = "Inquire statement identifies an internal file";
+ break;
+
default:
p = "Unknown error code";
break;
diff --git a/libgfortran/runtime/fpu.c b/libgfortran/runtime/fpu.c
index ecef0be3cd..79079ff693 100644
--- a/libgfortran/runtime/fpu.c
+++ b/libgfortran/runtime/fpu.c
@@ -1,5 +1,5 @@
/* Set FPU mask.
- Copyright (C) 2005-2014 Free Software Foundation, Inc.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
Contributed by Francois-Xavier Coudert <coudert@clipper.ens.fr>
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/in_pack_generic.c b/libgfortran/runtime/in_pack_generic.c
index aab155df68..b121a70b74 100644
--- a/libgfortran/runtime/in_pack_generic.c
+++ b/libgfortran/runtime/in_pack_generic.c
@@ -1,5 +1,5 @@
/* Generic helper function for repacking arrays.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2015 Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/in_unpack_generic.c b/libgfortran/runtime/in_unpack_generic.c
index 18855e1b68..179d6ff56a 100644
--- a/libgfortran/runtime/in_unpack_generic.c
+++ b/libgfortran/runtime/in_unpack_generic.c
@@ -1,5 +1,5 @@
/* Generic helper function for repacking arrays.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2015 Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c
index a103c554be..3c66a30fff 100644
--- a/libgfortran/runtime/main.c
+++ b/libgfortran/runtime/main.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Andy Vaught and Paul Brook <paul@nowt.org>
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <errno.h>
#ifdef HAVE_UNISTD_H
@@ -70,23 +71,18 @@ static int argc_save;
static char **argv_save;
static const char *exe_path;
-static int please_free_exe_path_when_done;
+static bool 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], *path;
- const char *cwd;
+ char *cwd, *path;
/* This can only happen if store_exe_path is called multiple times. */
if (please_free_exe_path_when_done)
@@ -95,13 +91,27 @@ store_exe_path (const char * argv0)
/* 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)
+ ssize_t len, psize = 256;
+ while (1)
{
- buf[len] = '\0';
- exe_path = strdup (buf);
- please_free_exe_path_when_done = 1;
- return;
+ path = xmalloc (psize);
+ len = readlink ("/proc/self/exe", path, psize);
+ if (len < 0)
+ {
+ free (path);
+ break;
+ }
+ else if (len < psize)
+ {
+ path[len] = '\0';
+ exe_path = strdup (path);
+ free (path);
+ please_free_exe_path_when_done = true;
+ return;
+ }
+ /* The remaining option is len == psize. */
+ free (path);
+ psize *= 4;
}
#endif
@@ -117,12 +127,29 @@ store_exe_path (const char * argv0)
#endif
{
exe_path = argv0;
- please_free_exe_path_when_done = 0;
+ please_free_exe_path_when_done = false;
return;
}
#ifdef HAVE_GETCWD
- cwd = getcwd (buf, sizeof (buf));
+ size_t cwdsize = 256;
+ while (1)
+ {
+ cwd = xmalloc (cwdsize);
+ if (getcwd (cwd, cwdsize))
+ break;
+ else if (errno == ERANGE)
+ {
+ free (cwd);
+ cwdsize *= 4;
+ }
+ else
+ {
+ free (cwd);
+ cwd = NULL;
+ break;
+ }
+ }
#else
cwd = NULL;
#endif
@@ -130,7 +157,7 @@ store_exe_path (const char * argv0)
if (!cwd)
{
exe_path = argv0;
- please_free_exe_path_when_done = 0;
+ please_free_exe_path_when_done = false;
return;
}
@@ -138,10 +165,11 @@ store_exe_path (const char * argv0)
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);
+ path = xmalloc (pathlen);
snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0);
+ free (cwd);
exe_path = path;
- please_free_exe_path_when_done = 1;
+ please_free_exe_path_when_done = true;
}
diff --git a/libgfortran/runtime/memory.c b/libgfortran/runtime/memory.c
index d3b77de4b8..94a9c2af50 100644
--- a/libgfortran/runtime/memory.c
+++ b/libgfortran/runtime/memory.c
@@ -1,5 +1,5 @@
/* Memory management routines.
- Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -87,3 +87,17 @@ xcalloc (size_t nmemb, size_t size)
return p;
}
+
+
+void *
+xrealloc (void *ptr, size_t size)
+{
+ if (size == 0)
+ size = 1;
+
+ void *newp = realloc (ptr, size);
+ if (!newp)
+ os_error ("Memory allocation failure in xrealloc");
+
+ return newp;
+}
diff --git a/libgfortran/runtime/minimal.c b/libgfortran/runtime/minimal.c
new file mode 100644
index 0000000000..72a134a48d
--- /dev/null
+++ b/libgfortran/runtime/minimal.c
@@ -0,0 +1,210 @@
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ Contributed by Andy Vaught and Paul Brook <paul@nowt.org>
+
+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 <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+
+#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;
+}
+
+options_t options;
+
+/* This will be 0 for little-endian
+ machines and 1 for big-endian machines.
+
+ Currently minimal libgfortran only runs on little-endian devices
+ which don't support constructors so this is just a constant. */
+int big_endian = 0;
+
+static int argc_save;
+static char **argv_save;
+
+static const char *exe_path;
+
+/* recursion_check()-- It's possible for additional errors to occur
+ * during fatal error processing. We detect this condition here and
+ * exit with code 4 immediately. */
+
+#define MAGIC 0x20DE8101
+
+static void
+recursion_check (void)
+{
+ static int magic = 0;
+
+ /* Don't even try to print something at this point */
+ if (magic == MAGIC)
+ sys_abort ();
+
+ magic = MAGIC;
+}
+
+
+/* os_error()-- Operating system error. We get a message from the
+ * operating system, show it and leave. Some operating system errors
+ * are caught and processed by the library. If not, we come here. */
+
+void
+os_error (const char *message)
+{
+ recursion_check ();
+ printf ("Operating system error: ");
+ printf ("%s\n", message);
+ exit (1);
+}
+iexport(os_error);
+
+
+/* void runtime_error()-- These are errors associated with an
+ * invalid fortran program. */
+
+void
+runtime_error (const char *message, ...)
+{
+ va_list ap;
+
+ recursion_check ();
+ printf ("Fortran runtime error: ");
+ va_start (ap, message);
+ vprintf (message, ap);
+ va_end (ap);
+ printf ("\n");
+ exit (2);
+}
+iexport(runtime_error);
+
+/* void runtime_error_at()-- These are errors associated with a
+ * run time error generated by the front end compiler. */
+
+void
+runtime_error_at (const char *where, const char *message, ...)
+{
+ va_list ap;
+
+ recursion_check ();
+ printf ("%s", where);
+ printf ("\nFortran runtime error: ");
+ va_start (ap, message);
+ vprintf (message, ap);
+ va_end (ap);
+ printf ("\n");
+ exit (2);
+}
+iexport(runtime_error_at);
+
+
+void
+runtime_warning_at (const char *where, const char *message, ...)
+{
+ va_list ap;
+
+ printf ("%s", where);
+ printf ("\nFortran runtime warning: ");
+ va_start (ap, message);
+ vprintf (message, ap);
+ va_end (ap);
+ printf ("\n");
+}
+iexport(runtime_warning_at);
+
+
+/* void internal_error()-- These are this-can't-happen errors
+ * that indicate something deeply wrong. */
+
+void
+internal_error (st_parameter_common *cmp, const char *message)
+{
+ recursion_check ();
+ printf ("Internal Error: ");
+ printf ("%s", message);
+ printf ("\n");
+
+ /* This function call is here to get the main.o object file included
+ when linking statically. This works because error.o is supposed to
+ be always linked in (and the function call is in internal_error
+ because hopefully it doesn't happen too often). */
+ stupid_function_name_for_static_linking();
+
+ exit (3);
+}
+
+
+/* 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_args (int argc, char **argv)
+{
+ argc_save = argc;
+ argv_save = argv;
+ exe_path = argv[0];
+}
+iexport(set_args);
+
+
+/* Retrieve the saved values of the command line arguments. */
+
+void
+get_args (int *argc, char ***argv)
+{
+ *argc = argc_save;
+ *argv = argv_save;
+}
+
+/* sys_abort()-- Terminate the program showing backtrace and dumping
+ core. */
+
+void
+sys_abort (void)
+{
+ /* If backtracing is enabled, print backtrace and disable signal
+ handler for ABRT. */
+ if (options.backtrace == 1
+ || (options.backtrace == -1 && compile_options.backtrace == 1))
+ {
+ printf ("\nProgram aborted.\n");
+ }
+
+ abort();
+}
diff --git a/libgfortran/runtime/pause.c b/libgfortran/runtime/pause.c
index ffc6192210..89473aeb57 100644
--- a/libgfortran/runtime/pause.c
+++ b/libgfortran/runtime/pause.c
@@ -1,5 +1,5 @@
/* Implementation of the PAUSE statement.
- Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/select.c b/libgfortran/runtime/select.c
index eeb418ae79..0d68393d08 100644
--- a/libgfortran/runtime/select.c
+++ b/libgfortran/runtime/select.c
@@ -1,5 +1,5 @@
/* Implement the SELECT statement for character variables.
- Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/select_inc.c b/libgfortran/runtime/select_inc.c
index 6ce80b05e3..76966ec742 100644
--- a/libgfortran/runtime/select_inc.c
+++ b/libgfortran/runtime/select_inc.c
@@ -1,5 +1,5 @@
/* Implement the SELECT statement for character variables.
- Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
This file is part of the GNU Fortran runtime library (libgfortran).
diff --git a/libgfortran/runtime/stop.c b/libgfortran/runtime/stop.c
index 7832ef883d..5c5483bd53 100644
--- a/libgfortran/runtime/stop.c
+++ b/libgfortran/runtime/stop.c
@@ -1,5 +1,5 @@
/* Implementation of the STOP statement.
- Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
This file is part of the GNU Fortran runtime library (libgfortran).
@@ -83,8 +83,7 @@ report_exception (void)
/* A numeric STOP statement. */
-extern void stop_numeric (GFC_INTEGER_4)
- __attribute__ ((noreturn));
+extern _Noreturn void stop_numeric (GFC_INTEGER_4);
export_proto(stop_numeric);
void
@@ -102,8 +101,7 @@ stop_numeric (GFC_INTEGER_4 code)
/* A Fortran 2008 numeric STOP statement. */
-extern void stop_numeric_f08 (GFC_INTEGER_4)
- __attribute__ ((noreturn));
+extern _Noreturn void stop_numeric_f08 (GFC_INTEGER_4);
export_proto(stop_numeric_f08);
void
@@ -136,8 +134,7 @@ stop_string (const char *string, GFC_INTEGER_4 len)
initiates error termination of execution." Thus, error_stop_string returns
a nonzero exit status code. */
-extern void error_stop_string (const char *, GFC_INTEGER_4)
- __attribute__ ((noreturn));
+extern _Noreturn void error_stop_string (const char *, GFC_INTEGER_4);
export_proto(error_stop_string);
void
@@ -154,8 +151,7 @@ error_stop_string (const char *string, GFC_INTEGER_4 len)
/* A numeric ERROR STOP statement. */
-extern void error_stop_numeric (GFC_INTEGER_4)
- __attribute__ ((noreturn));
+extern _Noreturn void error_stop_numeric (GFC_INTEGER_4);
export_proto(error_stop_numeric);
void
diff --git a/libgfortran/runtime/string.c b/libgfortran/runtime/string.c
index a7f68bf5aa..3c339da22a 100644
--- a/libgfortran/runtime/string.c
+++ b/libgfortran/runtime/string.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Paul Brook
This file is part of the GNU Fortran 95 runtime library (libgfortran).
@@ -24,6 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgfortran.h"
#include <string.h>
+#include <stdlib.h>
/* Given a fortran string, return its length exclusive of the trailing
@@ -90,6 +91,63 @@ cf_strcpy (char *dest, gfc_charlen_type dest_len, const char *src)
}
+#ifndef HAVE_STRNLEN
+static size_t
+strnlen (const char *s, size_t maxlen)
+{
+ for (size_t ii = 0; ii < maxlen; ii++)
+ {
+ if (s[ii] == '\0')
+ return ii;
+ }
+ return maxlen;
+}
+#endif
+
+
+#ifndef HAVE_STRNDUP
+static char *
+strndup (const char *s, size_t n)
+{
+ size_t len = strnlen (s, n);
+ char *p = malloc (len + 1);
+ if (!p)
+ return NULL;
+ memcpy (p, s, len);
+ p[len] = '\0';
+ return p;
+}
+#endif
+
+
+/* Duplicate a non-null-terminated Fortran string to a malloced
+ null-terminated C string. */
+
+char *
+fc_strdup (const char *src, gfc_charlen_type src_len)
+{
+ gfc_charlen_type n = fstrlen (src, src_len);
+ char *p = strndup (src, n);
+ if (!p)
+ os_error ("Memory allocation failed in fc_strdup");
+ return p;
+}
+
+
+/* Duplicate a non-null-terminated Fortran string to a malloced
+ null-terminated C string, without getting rid of trailing
+ blanks. */
+
+char *
+fc_strdup_notrim (const char *src, gfc_charlen_type src_len)
+{
+ char *p = strndup (src, src_len);
+ if (!p)
+ os_error ("Memory allocation failed in fc_strdup");
+ return p;
+}
+
+
/* Given a fortran string and an array of st_option structures, search through
the array to find a match. If the option is not found, we generate an error
if no default is provided. */