changeset 22134:a51d5c5c71e6

handle gfortran and f2c calling conventions separately * configure.ac: New option --enable-fortran-calling-convention. Explicitly define config.h macros for gfortran, f2c, Cray, and Visual Fortran options. * f77-fcn.h: Handle gfortran separately from f2c. (F77_CHAR_ARG_LEN_TYPE, F77_DBLE, F77_REAL, F77_DBLE_CMPLX, F77_CMPLX, F77_INT, F77_INT4, F77_LOGICAL, F77_CMPLX_ARG, F77_CONST_CMPLX_ARG, F77_DBLE_CMPLX_ARG, F77_CONST_DBLE_CMPLX_ARG): New macros. * f77-fcn.c (xstopx): Use F77_CHAR_ARG_LEN_TYPE.
author John W. Eaton <jwe@octave.org>
date Mon, 18 Jul 2016 09:56:41 -0400
parents 59cadee1c74b
children 407c66ae1e20
files configure.ac liboctave/cruft/misc/f77-fcn.c liboctave/cruft/misc/f77-fcn.h
diffstat 3 files changed, 110 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Sun Jul 17 12:42:37 2016 -0400
+++ b/configure.ac	Mon Jul 18 09:56:41 2016 -0400
@@ -668,7 +668,6 @@
   AC_MSG_ERROR([A Fortran compiler is required])
 fi
 
-## Determine calling conventions for Fortran compiler
 AC_F77_LIBRARY_LDFLAGS
 AC_F77_DUMMY_MAIN
 AC_F77_WRAPPERS
@@ -706,6 +705,34 @@
   ;;
 esac
 
+if test $ac_cv_f77_compiler_gnu = yes; then
+  FORTRAN_CALLING_CONVENTION=gfortran
+else
+  FORTRAN_CALLING_CONVENTION=unknown
+fi
+AC_ARG_ENABLE([fortran-calling-convention],
+  [AS_HELP_STRING([--enable-fortran-calling-convention=OPTION],
+    [Select C++ to Fortran calling convention.  "gfortran" should be detected automatically.  Other options are "cray", "visual-fortran", or "f2c".])],
+  [FORTRAN_CALLING_CONVENTION="$enableval"], [])
+
+case "$FORTRAN_CALLING_CONVENTION" in
+  gfortran)
+    AC_DEFINE(F77_USES_GFORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the gfortran calling convention.])
+  ;;
+  cray)
+    AC_DEFINE(F77_USES_CRAY_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Cray Fortran calling convention.])
+  ;;
+  visual-fortran)
+    AC_DEFINE(F77_USES_VISUAL_FORTRAN_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the Visual Fortran calling convention.])
+  ;;
+  f2c)
+    AC_DEFINE(F77_USES_F2C_CALLING_CONVENTION, 1, [Define to 1 if calling Fortran from C++ should use the f2c calling convention.])
+  ;;
+  *)
+    AC_MSG_ERROR([to build Octave, the C++ to Fortran calling convention must be known.])
+  ;;
+esac
+
 if test -n "$FFLAGS"; then
   AC_MSG_NOTICE([defining FFLAGS to be $FFLAGS])
 fi
@@ -715,7 +742,7 @@
 AC_SUBST(F77_APPEND_EXTRA_UNDERSCORE)
 
 if test -z "$F77"; then
-  AC_MSG_ERROR([in order to build Octave, you must have a compatible Fortran compiler or wrapper script for f2c that functions as a Fortran compiler installed and in your path.  See the file INSTALL for more information.])
+  AC_MSG_ERROR([to build Octave, you must have a compatible Fortran compiler or wrapper script for f2c that functions as a Fortran compiler installed and in your path.  See the file INSTALL for more information.])
 fi
 
 OCTAVE_CHECK_FUNC_FORTRAN_ISNAN
@@ -756,7 +783,7 @@
       OCTAVE_CHECK_SIZEOF_FORTRAN_INTEGER
     fi
     if test $octave_cv_sizeof_fortran_integer = no; then
-      AC_MSG_ERROR([in order to build Octave with 64-bit indexing support your Fortran compiler must have an option for setting the default integer size to 8 bytes.  See the file INSTALL for more information.])
+      AC_MSG_ERROR([to build Octave with 64-bit indexing support your Fortran compiler must have an option for setting the default integer size to 8 bytes.  See the file INSTALL for more information.])
     fi
   else
     AC_MSG_ERROR([your Fortran compiler must have an option to make integers the same size as octave_idx_type ($OCTAVE_IDX_TYPE).  See the file INSTALL for more information.])
--- a/liboctave/cruft/misc/f77-fcn.c	Sun Jul 17 12:42:37 2016 -0400
+++ b/liboctave/cruft/misc/f77-fcn.c	Mon Jul 18 09:56:41 2016 -0400
@@ -36,15 +36,21 @@
 
    XSTOPX jumps back to the entry point for the Fortran function that
    called us.  Then the calling function should do whatever cleanup
-   is necessary.  */
+   is necessary.
+
+   Note that the order of arguments for the Visual Fortran function
+   signature is the same as for gfortran and f2c only becuase there is
+   a single assumed size character string argument.  Visual Fortran
+   inserts the length after each character string argument, f2c appends
+   all length arguments at the end of the parameter list, and gfortran
+   appends length arguments for assumed size character strings to the
+   end of the list (ignoring others).  */
 
 F77_RET_T
 #if defined (F77_USES_CRAY_CALLING_CONVENTION)
 F77_FUNC (xstopx, XSTOPX) (octave_cray_ftn_ch_dsc desc)
-#elif defined (F77_USES_VISUAL_FORTRAN_CALLING_CONVENTION)
-F77_FUNC (xstopx, XSTOPX) (const char *s, int slen)
 #else
-F77_FUNC (xstopx, XSTOPX) (const char *s, long slen)
+F77_FUNC (xstopx, XSTOPX) (const char *s, F77_CHAR_ARG_LEN_TYPE slen)
 #endif
 {
 #if defined (F77_USES_CRAY_CALLING_CONVENTION)
--- a/liboctave/cruft/misc/f77-fcn.h	Sun Jul 17 12:42:37 2016 -0400
+++ b/liboctave/cruft/misc/f77-fcn.h	Mon Jul 18 09:56:41 2016 -0400
@@ -86,13 +86,10 @@
 
 The following macros are used for handling Fortran <-> C calling
 conventions.  They are defined below for three different types of
-systems, Cray (possibly now obsolete), Visual Fortran, and any system
-that is compatible with the f2c calling conventions, including g77 and
-gfortran.  Note that gfortran is not completely compatible with the
-f2c calling conventions, but that we only use the parts that are
-compatible.  For example, f2c and gfortran differ in the way they
-handle Fortran functions that return complex values, but Octave does
-not call any Fortran functions like that directly from C or C++.
+systems, Cray (possibly now obsolete), Visual Fortran, and gfortran.
+Note that we don't attempt to handle Fortran functions, we always use
+subroutine wrappers for them and pass the return value as an extra
+argument.
 
 Use these macros to pass character strings from C to Fortran:
 
@@ -144,7 +141,10 @@
 
 #include <fortran.h>
 
-/* Use these macros to pass character strings from C to Fortran.  */
+/* Use these macros to pass character strings from C to Fortran.  Cray
+   Fortran uses a descriptor structure to pass a pointer to the string
+   and the length in a single argument.  */
+
 #define F77_CHAR_ARG(x) octave_make_cray_ftn_ch_dsc (x, strlen (x))
 #define F77_CONST_CHAR_ARG(x) \
   octave_make_cray_const_ftn_ch_dsc (x, strlen (x))
@@ -153,9 +153,10 @@
 #define F77_CXX_STRING_ARG(x) \
   octave_make_cray_const_ftn_ch_dsc (x.c_str (), x.length ())
 #define F77_CHAR_ARG_LEN(l)
+#define F77_CHAR_ARG_LEN_TYPE
+#define F77_CHAR_ARG_LEN_DECL
 #define F77_CHAR_ARG_DECL octave_cray_ftn_ch_dsc
 #define F77_CONST_CHAR_ARG_DECL octave_cray_ftn_ch_dsc
-#define F77_CHAR_ARG_LEN_DECL
 
 /* Use these macros to write C-language functions that accept
    Fortran-style character strings.  */
@@ -171,6 +172,7 @@
    supposed to act like Fortran subroutines.  F77_NORETURN is intended
    to be used as the last statement of such a function that has been
    tagged with a "noreturn" attribute.  */
+
 #define F77_RETURN(retval) return retval;
 #if defined (HAVE_OCTAVE_NORETURN_ATTR)
 #  define F77_NORETURN(retval)
@@ -223,19 +225,23 @@
   
 #elif defined (F77_USES_VISUAL_FORTRAN_CALLING_CONVENTION)
 
-/* Use these macros to pass character strings from C to Fortran.  */
+/* Use these macros to pass character strings from C to Fortran.
+   Visual Fortran inserts the length after each character string
+   argument.  */
+
 #define F77_CHAR_ARG(x) x, strlen (x)
 #define F77_CONST_CHAR_ARG(x) F77_CHAR_ARG (x)
 #define F77_CHAR_ARG2(x, l) x, l
 #define F77_CONST_CHAR_ARG2(x, l) F77_CHAR_ARG2 (x, l)
 #define F77_CXX_STRING_ARG(x) F77_CONST_CHAR_ARG2 (x.c_str (), x.length ())
 #define F77_CHAR_ARG_LEN(l)
-#define F77_CHAR_ARG_DECL char *, int
-#define F77_CONST_CHAR_ARG_DECL const char *, int
+#define F77_CHAR_ARG_LEN_TYPE int
 #define F77_CHAR_ARG_LEN_DECL
+#define F77_CHAR_ARG_DECL char *, F77_CHAR_ARG_LEN_TYPE
+#define F77_CONST_CHAR_ARG_DECL const char *, F77_CHAR_ARG_LEN_TYPE
 
-#define F77_CHAR_ARG_DEF(s, len) char *s, int len
-#define F77_CONST_CHAR_ARG_DEF(s, len) const char *s, int len
+#define F77_CHAR_ARG_DEF(s, len) char *s, F77_CHAR_ARG_LEN_TYPE len
+#define F77_CONST_CHAR_ARG_DEF(s, len) const char *s, F77_CHAR_ARG_LEN_TYPE len
 #define F77_CHAR_ARG_LEN_DEF(len)
 #define F77_CHAR_ARG_USE(s) s
 #define F77_CHAR_ARG_LEN_USE(s, len) len
@@ -245,9 +251,17 @@
 #define F77_RETURN(retval) return;
 #define F77_NORETURN(retval)
 
-#else
+#elif defined (F77_USES_GFORTRAN_CALLING_CONVENTION)
+
+/* Use these macros to pass character strings from C to Fortran.
+   gfortran appends length arguments for assumed size character
+   strings to the and ignores others.
 
-/* Assume f2c-compatible calling convention.  */
+   FIXME: I don't think we correctly handle the case of mixing some
+   fixed-length and some assumed-length character string arguments as
+   we don't handle each case separately, so it seems there could be
+   mismatch?  However, I don't think we currently have to handle this
+   case in Octave.  */
 
 #define F77_CHAR_ARG(x) x
 #define F77_CONST_CHAR_ARG(x) F77_CHAR_ARG (x)
@@ -255,13 +269,47 @@
 #define F77_CONST_CHAR_ARG2(x, l) F77_CHAR_ARG2 (x, l)
 #define F77_CXX_STRING_ARG(x) F77_CONST_CHAR_ARG2 (x.c_str (), x.length ())
 #define F77_CHAR_ARG_LEN(l) , l
+#define F77_CHAR_ARG_LEN_TYPE int
+#define F77_CHAR_ARG_LEN_DECL , F77_CHAR_ARG_LEN_TYPE
 #define F77_CHAR_ARG_DECL char *
 #define F77_CONST_CHAR_ARG_DECL const char *
-#define F77_CHAR_ARG_LEN_DECL , long
 
 #define F77_CHAR_ARG_DEF(s, len) char *s
 #define F77_CONST_CHAR_ARG_DEF(s, len) const char *s
-#define F77_CHAR_ARG_LEN_DEF(len) , long len
+#define F77_CHAR_ARG_LEN_DEF(len) , F77_CHAR_ARG_LEN_TYPE len
+#define F77_CHAR_ARG_USE(s) s
+#define F77_CHAR_ARG_LEN_USE(s, len) len
+
+#define F77_RET_T void
+
+#define F77_RETURN(retval) return retval;
+#if defined (HAVE_OCTAVE_NORETURN_ATTR)
+#  define F77_NORETURN(retval)
+#else
+#  define F77_NORETURN(retval) return retval;
+#endif
+
+#elif defined (F77_USES_F2C_CALLING_CONVENTION)
+
+/* Assume f2c-compatible calling convention.  */
+
+/* Use these macros to pass character strings from C to Fortran.  f2c
+   appends all length arguments at the end of the parameter list.  */
+
+#define F77_CHAR_ARG(x) x
+#define F77_CONST_CHAR_ARG(x) F77_CHAR_ARG (x)
+#define F77_CHAR_ARG2(x, l) x
+#define F77_CONST_CHAR_ARG2(x, l) F77_CHAR_ARG2 (x, l)
+#define F77_CXX_STRING_ARG(x) F77_CONST_CHAR_ARG2 (x.c_str (), x.length ())
+#define F77_CHAR_ARG_LEN(l) , l
+#define F77_CHAR_ARG_LEN_TYPE long
+#define F77_CHAR_ARG_LEN_DECL , F77_CHAR_ARG_LEN_TYPE
+#define F77_CHAR_ARG_DECL char *
+#define F77_CONST_CHAR_ARG_DECL const char *
+
+#define F77_CHAR_ARG_DEF(s, len) char *s
+#define F77_CONST_CHAR_ARG_DEF(s, len) const char *s
+#define F77_CHAR_ARG_LEN_DEF(len) , F77_CHAR_ARG_LEN_TYPE len
 #define F77_CHAR_ARG_USE(s) s
 #define F77_CHAR_ARG_LEN_USE(s, len) len
 
@@ -274,6 +322,10 @@
 #  define F77_NORETURN(retval) return retval;
 #endif
 
+#else
+
+#error "unknown C++ to Fortran calling convention"
+
 #endif
 
 #define F77_DBLE double
@@ -294,7 +346,6 @@
  memcpy (cs, F77_CHAR_ARG_USE (s), F77_CHAR_ARG_LEN_USE (s, len)); \
  cs[F77_CHAR_ARG_LEN_USE(s, len)] = '\0'
 
-
 OCTAVE_NORETURN OCTAVE_API extern
 F77_RET_T
 F77_FUNC (xstopx, XSTOPX) (F77_CONST_CHAR_ARG_DECL