[comp.sources.misc] v20i066: cfortran - a bridge between C and FORTRAN, Part01/02

burow@cernvax.cern.ch (Burkhard Burow) (06/26/91)

Submitted-by: Burkhard Burow <burow@cernvax.cern.ch>
Posting-number: Volume 20, Issue 66
Archive-name: cfortran/part01
Environment: FORTRAN, MIPS, AIX, SGI, DEC 

Utility name:    cfortran.h
Source language: C
Purpose:         Help make mixing C and FORTRAN easy and machine independant.
Machines/OS: MIPS cc and f77 2.0. (e.g. Silicon Graphics, DECstations, ...)
             IBM AIX XL C and FORTRAN Compiler/6000 Version 01.01.0000.0000
             VAX VMS CC 3.1 and FORTRAN 5.4.

The following contains:
cfortran.doc - explaining how to use cfortran.h
cfortran.h   - a C header file which
               i)  allows for easy 'prototyping' of FORTRAN functions, so that
                   they may be called from C.
               ii) helps generate C wrappers for C functions so that the
                   functions may be called from FORTRAN.
cfortest.c
cfortex.for  - the source code to many simple demos of cfortran.h in action.

burkhard       burow@cernvax.cern.ch
---
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents:  cfortest.c cfortex.for cfortran.doc
# Wrapped by kent@sparky on Tue Jun 25 14:25:33 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 1 (of 2)."'
if test -f 'cfortest.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cfortest.c'\"
else
  echo shar: Extracting \"'cfortest.c'\" \(8968 characters\)
  sed "s/^X//" >'cfortest.c' <<'END_OF_FILE'
X/* cfortex.c */
X/* Burkhard Burow, burow%13313.hepnet@csa3.lbl.gov, U. of Toronto, 1991. */
X
X#include <stdio.h>
X#include "cfortran.h"
X
X#define   EQ_SELECT 1   /* To see the various examples select one of:
X        EASY_SELECT,  ST_SELECT, FT_SELECT, S1_SELECT, ABC_SELECT,  R_SELECT,
X         REV_SELECT, FCB_SELECT, EQ_SELECT, F0_SELECT,  FA_SELECT, FB_SELECT,
X          FC_SELECT,  FD_SELECT, FE_SELECT, FF_SELECT,  FG_SELECT, FH_SELECT,
X          FI_SELECT,  FJ_SELECT. */
X
X#ifdef EASY_SELECT
XPROTOCCALLSFSUB2(easy,PINT,INT)
X#define EASY(A,B)      CCALLSFSUB2(easy,PINT,INT, A,B)
X
Xmain() {
Xint a;
Xprintf("\nEASY EXAMPLE\n");
XEASY(a,7);
Xprintf("The FORTRAN routine easy(a,7) returns a = %d\n", a);
X}
X#endif
X
X#ifdef ST_SELECT
XPROTOCCALLSFSUB3(st,PSTRINGV,STRINGV,FLOAT)
X#define ST(A,B,C) CCALLSFSUB3(st,PSTRINGV,STRINGV,FLOAT,A,B,C)
X
Xint main() {
Xstatic char v[][5] = {"000 ", "1", "22", " "};
Xstatic char w[][9]  = {" ", "bb","ccc ","dddd"};
XST(v, w, 10.);
Xprintf("main:v=%s,%s,%s,%s. PSTRINGV => Has had trailing blanks stripped.\n",
X       v[0],v[1],v[2],v[3]);
Xprintf("main:w=%s,%s,%s,%s. STRINGV => malloc'd copy for FORTRAN=> C intact.\n"
X       ,w[0],w[1],w[2],w[3]);
X}
X#endif
X
X#ifdef FT_SELECT
XPROTOCCALLSFFUN3(STRING,ft,PSTRINGV,STRINGV,FLOAT)
X#define FT(A,B,C) CCALLSFFUN3(ft,PSTRINGV,STRINGV,FLOAT,A,B,C)
X
Xmain() {
Xstatic char v[][5] = {"000 ", "1", "22", " "};
Xstatic char w[][9]  = {" ", "bb","ccc ","dddd"};
Xfloat a = 10.0;
Xprintf("FT(v, w, a); returns:%s.\n",FT(v, w, a));
Xprintf("main:v=%s,%s,%s,%s. PSTRINGV => Has had trailing blanks stripped.\n",
X       v[0],v[1],v[2],v[3]);
Xprintf("main:w=%s,%s,%s,%s. STRINGV => malloc'd copy for FORTRAN=> C intact.\n"
X       ,w[0],w[1],w[2],w[3]);
X}
X#endif
X
X#ifdef S1_SELECT
XPROTOCCALLSFSUB1(s1,PSTRING)
X#define S1(A1)              CCALLSFSUB1(s1,PSTRING,A1)
XPROTOCCALLSFSUB1(forstr1,PSTRING)
X#define FORSTR1(A1)         CCALLSFSUB1(forstr1,PSTRING,A1)
X
Xmain() {
Xstatic char b[] = "abcdefghij", forb[13] = "abcdefghijkl";
XS1(b); FORSTR1(forb);
Xprintf("s1(b) returns b = %s; forstr1(forb) = returns forb = %s;\n", b, forb);
X}
X#endif
X
X#ifdef ABC_SELECT
XPROTOCCALLSFSUB3(abc,STRING,PSTRING,PSTRING)
X#define ABC(A1,A2,A3)       CCALLSFSUB3(abc,STRING,PSTRING,PSTRING,A1,A2,A3)
X
Xmain() {
Xstatic char aa[] = "one  ", bb[] = "two  ", cc[] = "three"; int i;
Xfor (i=0; i<10; i++) {printf("%s;%s;%s;\n",aa,bb,cc); ABC(aa,bb,cc);}
X}
X#endif
X
X#ifdef R_SELECT
XPROTOCCALLSFFUN1(FLOAT,r,INT)
X#define R(A1)               CCALLSFFUN1(r,INT,A1)
XPROTOCCALLSFFUN0(STRING,forstr2)
X#define FORSTR2()           CCALLSFFUN0(forstr2)
XPROTOCCALLSFFUN1(STRING,forstr,STRING)
X#define FORSTR(A1)          CCALLSFFUN1(forstr,STRING,A1)
X
Xmain() {
Xstatic char aa[] = "one";
Xint rrr = 333;
Xprintf("R(rrr=%d) returns int arg. as float:%f\n",rrr,R(rrr));
Xprintf("FORSTR(aa=%s) returns the string arg. as:%s<-end here\n",aa,FORSTR(aa));
Xprintf("FORSTR2() returns the string constant:%s<-end here\n",FORSTR2());
X}
X#endif
X
X#ifdef REV_SELECT
XPROTOCCALLSFFUN1(INT,frev,INTV)
X#define FREV(A1)               CCALLSFFUN1(frev,INTV,A1)
XPROTOCCALLSFSUB1(rev,INTV)
X#define REV(A1)                CCALLSFSUB1(rev,INTV,A1)
X
Xmain() {
Xstatic int a[] = {1,2};
Xprintf("REV(a[0,1]=%d,%d) returns:",a[0],a[1]);
XREV(a); printf("a[0,1]=%d,%d\n",a[0],a[1]);
Xprintf("FREV(a[0,1]=%d,%d) returns:",a[0],a[1]);
Xprintf("%d",FREV(a)); printf(" with a[0,1]=%d,%d\n",a[0],a[1]);
X}
X#endif
X
X#ifdef FCB_SELECT
XPROTOCCALLSFSUB0(ffcb)
X#define FFCB()                 CCALLSFSUB0(ffcb)
X
Xtypedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF;
X#define FCB COMMON_BLOCK(fcb)
Xextern FCB_DEF FCB;
X
Xmain() {
Xchar cv[14];
Xstatic char cw[4][14]    = {"C's w[0]", "C's w[1]", "C's w[2]", "C's w[3]"};
Xstatic char cx[2][3][14] = {"C's x[0][0]", "C's x[0][1]", "C's x[0][2]",
X                            "C's x[1][0]", "C's x[1][1]", "C's x[1][2]"};
XC2FCBSTR("C's V" ,FCB.v,0);
XC2FCBSTR(cw      ,FCB.w,1);
XC2FCBSTR(cx      ,FCB.x,2);
XFFCB();
XFCB2CSTR(FCB.v   ,cv   ,0);
XFCB2CSTR(FCB.w   ,cw   ,1);
XFCB2CSTR(FCB.x   ,cx   ,2);
Xprintf("FCB returns v = %s.\n",cv);
Xprintf("FCB returns w[1,2,3,4] = %s,%s,%s,%s.\n",cw[0],cw[1],cw[2],cw[3]);
Xprintf("FCB returns x[0,(1,2,3)] = %s,%s,%s.\n",cx[0][0],cx[0][1],cx[0][2]);
Xprintf("FCB returns x[1,(1,2,3)] = %s,%s,%s.\n",cx[1][0],cx[1][1],cx[1][2]);
X}
X#endif
X
X#ifdef EQ_SELECT
XPROTOCCALLSFSUB0(feq)
X#define FEQ()                 CCALLSFSUB0(feq)
X
X#define KWBANK 690
Xtypedef struct {
X  int nzebra; float gversn,zversn; int ixstor,ixdiv,ixcons; float fendq[16];
X  union {
X    struct {
X      int Lmain,Lr1;
X      union {float Ws[KWBANK]; int Iws[2];}u;
X    }s;
X    union {
X      int Lq[80];
X      struct {
X        int dummy[8];
X        union {float Q[2]; int Iq[2];}u;
X      }s;
X    }u;
X  }u;
X} GCBANK_DEF;
X#define lmain u.s.Lmain
X#define lr1   u.s.Lr1
X#define ws    u.s.u.Ws
X#define iws   u.s.u.Iws
X#define lq    u.u.Lq
X#define q     u.u.s.u.Q
X#define iq    u.u.s.u.Iq
X#define GCBANK COMMON_BLOCK(gcbank)
XGCBANK_DEF GCBANK;
X
Xmain() {
XFEQ();
Xprintf("GCBANK.nzebra       = %d.\n", GCBANK.nzebra);
Xprintf("GCBANK.gversn       = %f.\n", GCBANK.gversn);
Xprintf("GCBANK.zversn       = %f.\n", GCBANK.zversn);
Xprintf("GCBANK.ixstor       = %d.\n", GCBANK.ixstor);
Xprintf("GCBANK.ixcons       = %d.\n", GCBANK.ixcons);
Xprintf("GCBANK.fendq[15]    = %f.\n", GCBANK.fendq[15]);
Xprintf("GCBANK.lmain        = %d.\n", GCBANK.lmain);
Xprintf("GCBANK.lr1          = %d.\n", GCBANK.lr1);
Xprintf("GCBANK.ws[KWBANK-1] = %f.\n", GCBANK.ws[KWBANK-1]);
Xprintf("GCBANK.iq[0]        = %d.\n", GCBANK.iq[0]);
X}
X#endif
X
X/* The following functions are called by FORTRAN functions, as shown by the
X   remaining examples.
X   We redefine the C name of each routine called from FORTRAN so that the
X   FORTRAN call may use the C name, e.g. the next line. */
X#define EXIST ccallsc(exist)
Xvoid EXIST() {printf("EXIST: was called.\n");}
XFCALLSCSUB0(exist)
X
X#define CA ccallsc(ca)
Xvoid CA(int i) {printf("CA: had integer argument:%d.\n",i);}
XFCALLSCSUB1(ca,INT)
X
X#define CB ccallsc(cb)
Xvoid CB(int *i) {
Xprintf("CB: had pointer argument to integer:%d.\n",*i); *i*=2;}
XFCALLSCSUB1(cb,PINT)
X
X#define CC ccallsc(cc)
Xvoid CC(char *s) {printf("CC: had string argument:%s.\n",s);}
XFCALLSCSUB1(cc,STRING)
X
X#define CD ccallsc(cd)
Xvoid CD(char *s)
X{printf("CD: had string argument:%s.\n",s); strcpy(s,"to you 12345678");}
XFCALLSCSUB1(cd,PSTRING)
X
X#define CE ccallsc(ce)
Xvoid CE(char v[][5])
X{printf("CE: had string vector argument:%s,%s,%s.\n",v[0],v[1],v[2]);}
X#define ce_STRV_A1 TERM_CHARS(' ',1)
XFCALLSCSUB1(ce,STRINGV)
X
X#define CF ccallsc(cf)
Xvoid CF(char v[][5], int n)
X{int i;
Xprintf("CF: had %d string vector argument:",n);
Xfor (i=0; i<n-1; i++) printf("%s,",v[i]);
Xprintf("%s.\n",v[i]);
X}
X#define cf_STRV_A1 NUM_ELEM_ARG(2)
XFCALLSCSUB2(cf,STRINGV,INT)
X
X
X#define CG ccallsc(cg)
Xint CG() {return 1;}
XFCALLSCFUN0(INT,cg)
X
X#define CH ccallsc(ch)
Xchar *CH() {return "hello";}
XFCALLSCFUN0(STRING,ch)
X
X#define CI ccallsc(ci)
Xchar *CI(char v[][5]) {return v[3];}
X#define ci_STRV_A1 NUM_ELEMS(6)
XFCALLSCFUN1(STRING,ci,STRINGV)
X
X#define CJ ccallsc(cj)
Xchar *CJ(int v) {printf("CJ:v=%d\n",v);return "hello";}
XFCALLSCFUN1(STRING,cj,INT)
X
X#ifdef F0_SELECT
XPROTOCCALLSFSUB0(fexist)
X#define FEXIST()               CCALLSFSUB0(fexist)
X
Xmain() {FEXIST();}
X#endif
X
X#ifdef FA_SELECT
XPROTOCCALLSFSUB1(fa,INT)
X#define FA(A1)               CCALLSFSUB1(fa,INT,A1)
X
Xmain() {FA(1234);}
X#endif
X
X#ifdef FB_SELECT
XPROTOCCALLSFSUB1(fb,PINT)
X#define FB(A1)               CCALLSFSUB1(fb,PINT,A1)
X
Xmain()
X{int i,ii; i=ii=1234;
X FB(ii); printf("MAIN: FB(i=%d) returns with i=%d.\n",i,ii);}
X#endif
X
X#ifdef FC_SELECT
XPROTOCCALLSFSUB1(fc,STRING)
X#define FC(A1)               CCALLSFSUB1(fc,STRING,A1)
X
Xmain() {FC("hello");}
X#endif
X
X#ifdef FD_SELECT
XPROTOCCALLSFSUB1(fd,PSTRING)
X#define FD(A1)               CCALLSFSUB1(fd,PSTRING,A1)
X
Xmain()
X{static char i[] = "happy     "; static char ii[] = "happy      ";
X FD(ii); printf("MAIN: FD(i=%s) returns with i=%s.\n",i,ii);}
X#endif
X
X#ifdef FE_SELECT
XPROTOCCALLSFSUB1(fe,STRINGV)
X#define FE(A1)               CCALLSFSUB1(fe,STRINGV,A1)
X
Xmain()
X{static char v[][5] = {"0000", "1", "22", ""}; FE(v);}
X#endif
X
X#ifdef FF_SELECT
XPROTOCCALLSFSUB2(ff,STRINGV,INT)
X#define FF(A1,A2)               CCALLSFSUB2(ff,STRINGV,INT, A1,A2)
X
Xmain()
X{static char v[][5] = {"0000", "1", "22", ""};
X FF(v,sizeof(v)/sizeof v[0]);}
X#endif
X
X#ifdef FG_SELECT
XPROTOCCALLSFFUN0(INT,fg)
X#define FG()               CCALLSFFUN0(fg)
X
Xmain()
X{printf("FG() returns %d.\n",FG());}
X#endif
X
X#ifdef FH_SELECT
XPROTOCCALLSFFUN0(STRING,fh)
X#define FH()               CCALLSFFUN0(fh)
X
Xmain()
X{printf("FH() returns %s.\n",FH());}
X#endif
X
X#ifdef FI_SELECT
XPROTOCCALLSFFUN1(STRING,fi,STRINGV)
X#define FI(A1)               CCALLSFFUN1(fi,STRINGV,A1)
X
Xmain()
X{static char v[][5] = {"0000", "1", "22", "333", "8", "9"};
X printf("FI(v) returns %s.\n",FI(v));}
X#endif
X
X#ifdef FJ_SELECT
XPROTOCCALLSFFUN1(STRING,fj,INT)
X#define FJ(A1)               CCALLSFFUN1(fj,INT,A1)
X
Xmain()
X{ printf("FJ(2) returns %s.\n",FJ(2));}
X#endif
END_OF_FILE
  if test 8968 -ne `wc -c <'cfortest.c'`; then
    echo shar: \"'cfortest.c'\" unpacked with wrong size!
  fi
  # end of 'cfortest.c'
fi
if test -f 'cfortex.for' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cfortex.for'\"
else
  echo shar: Extracting \"'cfortex.for'\" \(4434 characters\)
  sed "s/^X//" >'cfortex.for' <<'END_OF_FILE'
XC cfortex.f
XC Burkhard Burow, University of Toronto, July 1990.
X
X      subroutine s1(b)
X      character*(*) b
X      character*(13) a
X      data a/'first'/
X      b = a
X      return
X      end
X
X      subroutine abc(a,b,c)
X      character*(*) b,a,c
X      character*(13) d
X      d = a
X      a = b
X      b = c
X      c = d
X      return
X      end
X
X      subroutine forstr1(b)
X      character*(*) b
X      character*(13) a
X      character*(13) forstr
X      data a/'firs'/
X      b = forstr(a)
X      return
X      end
X
X
X      subroutine EASY(a,b)
X      a = b
X      return
X      end
X
X      character*(*) function forstr(a)
X      character*(*) a
X      forstr = a
X      return
X      end
X
X      function r(i)
X      r = i
X      return
X      end
X
X      character*(*) function forstr2()
X      character*(13) a
X      data a/'first'/
X      forstr2 = a
X      return
X      end
X
X      character*(*) function ft(v, w, a)
X      character *(*) v(4), w(4)
X      print*,'FT:len(v(1 or 2 or 3 or 4))  =',len(v(1))
X      print*,'FT:len(w(1 or 2 or 3))    =',len(w(1))
X      print*,'FT:a = ',a
X      print*,'FT:v(1,2,3,4) =',v(1),',',v(2),',',v(3),',',v(4)
X      print*,'FT:w(1,2,3,4) =',w(1),',',w(2),',',w(3),',',w(4)
X      ft = v(1)
X      return
X      end
X
X      subroutine st(v, w, a)
X      character *(*) v(4), w(4)
X      print*,'ST:len(v(1 or 2 or 3 or 4))  =',len(v(1))
X      print*,'ST:len(w(1 or 2 or 3))    =',len(w(1))
X      print*,'ST:a = ',a
X      print*,'ST:v(1,2,3,4) =',v(1),',',v(2),',',v(3),',',v(4)
X      print*,'ST:w(1,2,3,4) =',w(1),',',w(2),',',w(3),',',w(4)
X      return
X      end
X
X      subroutine rev(a)
X      integer a(2),t
X      t    = a(1)
X      a(1) = a(2)
X      a(2) = t
X      return
X      end
X
X      integer function frev(a)
X      integer a(2)
X      frev = a(1)
X      a(1) = a(2)
X      a(2) = frev
X      return
X      end
X
X      subroutine ffcb()
X      common /fcb/  v,w,x
X      character *(13) v, w(4), x(3,2)
X      print*,'FFCB:v =',v,'.'
X      print*,'FFCB:w(1,2,3,4) =',w(1),',',w(2),',',w(3),',',w(4),'.'
X      print*,'FFCB:x([1,2,3],1) =',x(1,1),',',x(2,1),',',x(3,1),'.'
X      print*,'FFCB:x([1,2,3],2) =',x(1,2),',',x(2,2),',',x(3,2),'.'
X      v      = 'fcb v'
X      w(1)   = 'fcb w(1)'
X      w(2)   = 'fcb w(2)'
X      w(3)   = 'fcb w(3)'
X      x(1,1) = 'fcb x(1,1)'
X      x(2,1) = 'fcb x(2,1)'
X      x(3,1) = 'fcb x(3,1)'
X      x(1,2) = 'fcb x(1,2)'
X      x(2,2) = 'fcb x(2,2)'
X      x(3,2) = 'fcb x(3,2)'
X      end
X
X      subroutine feq()
X      parameter (kwbank=690)
X      common/gcbank/nzebra,gversn,zversn,ixstor,ixdiv,ixcons,fendq(16)
X     +             ,lmain,lr1,ws(kwbank)
X      dimension iq(2),q(2),lq(80),iws(2)
X      equivalence (q(1),iq(1),lq(9)),(lq(1),lmain) ,(iws(1),ws(1))
X      nzebra     = 1
X      gversn     = 2
X      zversn     = 3
X      ixstor     = 4
X      ixcons     = 5
X      fendq(16)  = 6
X      lmain      = 7
X      lr1        = 8
X      ws(kwbank) = 9
X      lq(9)      = 10
X      end
X
X      subroutine fexist()
X      print*,'FEXIST: was called'
X      call exist()
X      return
X      end
X
X      subroutine fa(i)
X      integer i
X      print*,'FA: integer argument =',i
X      call ca(i)
X      return
X      end
X
X      subroutine fb(i)
X      integer i
X      print*,'FB: integer argument =',i
X      i = i*2
X      call cb(i)
X      return
X      end
X
X      subroutine fc(b)
X      character*(*) b
X      print*,'FC: string argument =',b
X      call cc(b)
X      return
X      end
X
X      subroutine fd(b)
X      character*(*) b
X      character*(13) a
X      data a/'birthday'/
X      b = a
X      call cd(b)
X      return
X      end
X
X      subroutine fe(v)
X      character*(*) v(4)
X      print*,'FE:len(v(1 or 2 or 3 or 4))  =',len(v(1))
X      print*,'FE:v(1,2,3,4) =',v(1),',',v(2),',',v(3),',',v(4)
X      call ce(v)
X      return
X      end
X
X      subroutine ff(v,n)
X      character*(*) v(4)
X      print*,'FF:len(v(1 or 2 or 3 or 4))  =',len(v(1))
X      print*,'FF:v(1,2,3,4) =',v(1),',',v(2),',',v(3),',',v(4)
X      print*,'FF:n =',n
X      call cf(v,n)
X      return
X      end
X
X      integer function fg()
X      integer cg
X      fg = cg()
X      return
X      end
X
X      character*(*) function fh()
X      character*200 ch
X      fh = ch()
X      return
X      end
X
X      character*(*) function fi(v)
X      character*(*) v(6)
X      character*200 ci
X      fi = ci(v)
X      return
X      end
X
X      character*(*) function fj(v)
X      integer v
X      character*200 cj
X      print*,'FJ:v =',v
X      fj = cj(v)
X      return
X      end
X
END_OF_FILE
  if test 4434 -ne `wc -c <'cfortex.for'`; then
    echo shar: \"'cfortex.for'\" unpacked with wrong size!
  fi
  # end of 'cfortex.for'
fi
if test -f 'cfortran.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cfortran.doc'\"
else
  echo shar: Extracting \"'cfortran.doc'\" \(27512 characters\)
  sed "s/^X//" >'cfortran.doc' <<'END_OF_FILE'
X/* cfortran.doc */
X/* Burkhard Burow, burow@vxdesy.desy.de, U. of Toronto, 1991. */
X
X
X                CFORTRAN 1.2 for UNIX Machines and for VAX VMS
X
XHistory:
X- 1.0 for VAX VMS using C 3.1 and FORTRAN 5.4.                        Oct. '90.
X- 1.0 for Silicon Graphics using Mips Computer System 2.0 f77 and cc. Feb. '91.
X          [Port of C calls FORTRAN half only.]
X- 1.1 for Mips Computer System 2.0 f77 and cc.                        Mar. '91.
X          [Runs on at least: Silicon Graphics IRIX 3.3.1
X                             DECstations with Ultrix V4.1]
X- 1.2 Internals are simpler, smaller, faster, stronger.               May  '91.
X      Mips version works on IBM RS/6000, this is now called the unix version.
X- 1.3 UNIX and VAX VMS versions are merged into a single cfortran.h.  June '91.
X      C can manipulate (arrays of) strings in FORTRAN common blocks.
X
X
XI Introduction
X--------------
X
XCFORTRAN is an easy-to-use powerful bridge between C and FORTRAN. It provides a
Xcompletely transparent, machine independant, interface  between C and FORTRAN
Xroutines (= subroutines and/or functions).
X
XThe complete CFORTRAN package consists of 4 files. They are this introduction,
Xcfortran.doc, the engine in cfortran.h, examples in cfortest.c and
Xcfortex.f/or. [cfortex.for under VMS, cfortex.f under UNIX.]
X
XTo run the example do the following:
X
XRS/6000> cc -Drs6000 -c cfortest.c && xlf -o cfortest cfortest.o cfortex.f
XRS/6000> cfortest
X
Xor
X
XMIPS> cc -o cfortest cfortest.c cfortex.f -lI77 -lU77 -lF77
XMIPS> cfortest
X
Xor
X
XVMS> define lnk$library sys$library:vaxcrtl
XVMS> cc cfortest.c
XVMS> fortran cfortex.for
XVMS> link/exec=cfortest cfortest,cfortex
XVMS> run cfortest
X
XBy changing the SELECTion ifdef of cfortest.c and recompiling you can try out
Xa dozen different few-line examples.
X
X
X
XThe benefits of using CFORTRAN include:
X1. Machine independant applications.
X
X2. Identical (within syntax) calls across languages, e.g.
XC FORTRAN
X      CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.)
X/* C*/
X           HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.);
X
X3. Each routine need ony be set up once in its lifetime. e.g.
X/* Setting up a FORTRAN routine to be called by C. Note that ID,...,VMX are
Xmerely the names of arguments. These tags must be unique w.r.t. each other but
Xare arbitrary. */
XPROTOCCALLSFSUB6(hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT)
X#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX)                 \
X     CCALLSFSUB6(hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \
X               ID,CHTITLE,NX,XMI,XMA,VMX)
X
X4. Routines, and the code calling them, can be coded naturally in the language
X   of choice. C routines may be coded with the natural assumption that they'll
X   only be called by C code. CFORTRAN does all the required work for FORTRAN
X   code to call C routines. Similarly CFORTRAN does all the work required for C
X   to call FORTRAN routines. Therefore:
X     - C programmers need not imbed FORTRAN argument passing mechanisms into
X       their code.
X     - FORTRAN code need not be converted into C code. i.e. The honed and
X       timehonored FORTRAN routines are called by C, not some new translation
X       from FORTRAN into C.
X
X5. CFORTRAN is contained within a single C include file, cfortran.h, weighing
X   in at ~1100 lines. cfortran.h currently supports VAX VMS, the IBM RS/6000
X   and machines using the MIPS RISC compilers. It should be portable to many
X   other platforms.
X
X6. STRINGS and VECTORS of STRINGS along with the usual simple arguments to
X   routines are supported as are functions returning STRINGS or numbers.
X
X7. CFORTRAN requires each routine to be exported to be explicitly set up. While
X   this need usually only be done once in a header file it would be best if
X   applications were required to do no work at all in order to cross languages.
X   CFORTRAN's simple syntax could be a convinient back-end for a program which
X   would export FORTRAN or C routines directly from the source code.
X
X
X                                    -----
X
XExample 1 - CFORTRAN has been used to make the C header file hbook.h,
X            which then gives any C programmer, e.g. example.c, full and
X            completely transparent access to CERN's HBOOK library of routines.
X            Each HBOOK routine required about 3 lines of simple code in
X            hbook.h. The example also demonstrates how FORTRAN common blocks
X            are defined and used.
X
X/* hbook.h */
X#include "cfortran.h"
X        :
XPROTOCCALLSFSUB6(hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT)
X#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \
X     CCALLSFSUB6(hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \
X               ID,CHTITLE,NX,XMI,XMA,VMX)
X        :
X/* end hbook.h */
X
X/* example.c */
X#include "hbook.h"
X        :
Xtypedef struct {
X  int lines;
X  int status[SIZE];
X  float p[SIZE];  /* momentum */
X} FAKE_DEF;
X#define FAKE COMMON_BLOCK(fake)
Xextern FAKE_DEF FAKE;
X        :
Xmain ()
X{
X        :
X           HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.);
X/* c.f. the call in FORTRAN:
X      CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.)
X*/
X        :
X  FAKE.p[7]=1.0;
X        :
X}
X
XN.B. i) The routine is language independant.
X    ii) hbook.h is machine independant.
X   iii) Applications using CFORTRAN'd routines are machine independant.
X
X                                    -----
X
XExample 2 - Many VMS System calls are most easily called from FORTRAN, but
X            CFORTRAN now gives you that ease in C.
X
X#include "cfortran.h"
X
XPROTOCCALLSFSUB3(lib$spawn, STRING,STRING,STRING)
X#define LIB$SPAWN(command,input_file,output_file) \
X     CCALLSFSUB3(lib$spawn, STRING,STRING,STRING, \
X                  command,input_file,output_file)
X
Xmain ()
X{
XLIB$SPAWN("set term/width=132","","");
X}
X
XObviously the 2 CFORTRAN lines above should be put into a header file along
Xwith the description of the other system calls, but as this example shows it's
Xnot much hassle to set up CFORTRAN for even a single call.
X
X                                    -----
X
XExample 3 - CFORTRAN and the source cstring.c create the cstring.obj library
X            which gives FORTRAN access to all the functions in C's system
X            library described by the system's C header file string.h.
X
XC     EXAMPLE.FOR
X      PROGRAM EXAMPLE
X      DIMENSION I(20), J(30)
X        :
X      CMEMCPY(I,J,7)
X        :
X      END
X
X/* cstring.c */
X#include <string.h>
X#include "cfortran.h"
X
X#undef fcallsc
X#define fcallsc(NAME) C/**/NAME
X
X        :
XFCALLSCSUB3(memcpy, PVOID, PVOID, INT)
X        :
X
XN.B. Other than a possible redefinition of fcallsc, cstring.c is machine
Xindependant. Unfortunately the names of C routines called by FORTRAN may
Xdiffer from  the name of the original C routine, e.g. cmemcpy vs. the original
Xmemcpy. This need never be the case if one has:
X
X   i) the original C source code for the routine.
XOR ii)a FORTRAN compiler, e.g. f77, which 'renames' routines.
XOR iii) a case sensitive linker.
X
XIf all the above fail, CFORTRAN, through fcallsc, makes it easy to ensure that
Xnames of C routines called by FORTRAN are modified from  the original only when
Xabsolutely neccessary, and if they are modified, that it is done consistently
Xfor any given FORTRAN compiler. [More details below in Section VI.]
X
X                                    -----
X
X
XII Using CFORTRAN
X-----------------
X
XThe user is asked to look at the source files CFORTEX.C and CFORTEX.FOR for
Xclarification by example.
X
XNote: CFORTRAN (ab)uses the null comment, /**/, kludge for the ANSI C
Xpreprocessor concatenation, ##, operator. In MIPS C this kludge is sensitive
Xto blanks prepending arguments to macros.
XTHEREFORE IN THE FOLLOWING MACRO DEFINITIONS YOU MAY NOT PREPEND argtype_i NOR
Xroutine_type WITH BLANK, ' ', CHARACTERS.
X
XNote: On the RS/6000, currently the only machine supporting ##, a global
Xreplace of /**/ by ## makes cfortran.h ANSI compliant.
X
XNote: On the RS/6000, if you use "xlf -qextname ...", which appends an
Xunderscore, '_', to all FORTRAN external references, then you must use,
X"cc -Dextname ..." so that cfortran.h also generates these underscores.
X
XNote: The calls to FORTRAN subroutines are expanded to code inside {....}. This
Xhas some undesirable side effects, e.g.
Xif (a==b) A_FORTRAN_SUBROUTINE(1,"Hello")  /* <-- No ';' allowed here. */
Xelse      A_FORTRAN_SUBROUTINE(1,"Hello")
XUnfortunately there is no fix in sight. (gcc extensions to C would offer a fix.)
X
XNote: At the moment only vectors of fixed length strings are supported in C. I
Xknow how and hope to support vectors of pointers to strings in the near future.
X
XNote: For those who wish to use CFORTRAN in large applications.
XThis release is intended to make it easy to get applications up and running.
XThis implies that applications are not as efficient as they could be:
X- The current mechanism is inefficient if a single header file is used to
X  describe a large library of FORTRAN functions. Code for a static wrapper fn.
X  is generated in each piece of C source code for each FORTRAN function
X  specified with the CCALLSFFUNn statement, irrespective of whether or not the
X  function is ever called. I have several ideas for how code for these wrappers
X  could be created, compiled and linked only once instead of once for each
X  piece of source code.
X- Code for several static utility routines internal to CFORTRAN is placed into
X  any source code which #include's cfortran.h. These routines should be in a
X  library.
X- The FORTRAN calls C half of the package could be split from the C calls
X  FORTRAN half.
X
X
Xi) Calling FORTRAN routines from C:
X   --------------------------------
X
XFORTRAN routines are prototyped by the following two macros.
X
XPROTOCCALLSFSUBn(routine_name, argtype_1, ..., argtype_n)
X
Xor
X
XPROTOCCALLSFFUNn(routine_type, routine_name, argtype_1, ..., argtype_n)
X
X
Xand are defined respectively by the following two macro usages.
X
X#define      ROUTINE_NAME(argname_1,...,argname_n) \
XCCALLSFSUBn(routine_name, argtype_1,...,argtype_n, \
X                          argname_1,...,argname_n)
X
X#define      ROUTINE_NAME(argname_1,...,argname_n) \
XCCALLSFFUNn(routine_name, argtype_1,...,argtype_n, \
X                          argname_1,...,argname_n)
X
XWhere:
X'n' = 0->7 (easily expanded in CFORTRAN.H to >7) stands for the number of
X    arguments to the routine.
XROUTINE_NAME = the C       name of the routine (IN UPPERCASE LETTERS).
Xroutine_name = the FORTRAN name of the routine (IN lowercase LETTERS).
Xroutine_type = the type of argument returned by FORTRAN functions.
X             = DOUBLE, FLOAT, INT, LOGICAL, LONG, STRING.
Xargtype_i    = the type of argument passed to the FORTRAN routine and must be
X               consistent in the definition and prototyping of the routine s.a.
X             = DOUBLE, FLOAT, INT, LOGICAL, LONG, STRING.
X             For vectors, i.e. 1 dim. arrays use
X             = DOUBLEV, FLOATV, INTV, LOGICALV, LONGV.
X             For vectors of vectors, 2 dim. arrays use
X             = DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, STRINGV.
X             For n-dim. arrays use
X             = DOUBLEV..nV's..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V.
X                N.B. Array dimensions and types are checked by the C compiler.
X             For routines changing the values of an argument, the keyword is
X                  prepended by a 'P'.
X             = PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSTRING, PSTRINGV.
X             For exceptional arguments which require no massaging to fit the
X                  argument passing mechanisms use:
X             = PVOID.
X                This is most useful for passing functions as arguments.
X                But note that although PVOID could be used to describe all
X                array arguments on most (all?) machines , it shouldn't be
X                because the C compiler can no longer check the type and
X                dimension of the array.
Xargname_i    = any valid unique C tag, but must be consistent in the definition
X               as shown.
X
XSome notes on (P)STRING(V):
X
XSTRING - If the argument is a fixed length character array, e.g. char ar[8];,
Xthe string is blank, ' ', padded on the right to fill out the array before
Xbeing passed to the FORTRAN routine. The useful size of the string is the same
Xin both languages, e.g. we pass ar[8] as character*7. If the argument is a
Xpointer, we cannot blank pad, and pass the length as strlen(argument). On
Xreturn from the FORTRAN routine, pointer arguments are not disturbed, arrays
Xhave the terminating '\0' replaced to its original position. i.e. The
Xpadding blanks are never visible to the C code.
X
XPSTRING - The argument is massaged as with STRING before being passed to the
XFORTRAN routine. On return, the argument has all trailing blanks removed,
Xregardless of whether the argument was a pointer or an array.
X
XN.B. Only char arrays are supported for (P)STRINGV. e.g. char bb[6][8];
X
XSTRINGV - The elements of the argument are copied into space malloc'd, and each
Xelement is padded with blanks. The useful size of each element is the same in
Xboth languages. Therefore char bb[6][8]; is equivalent to character*7 bb(6).
XOn return from the routine the malloc'd space is simply released.
X
XPSTRINGV - Since FORTRAN has no trailing '\0', elements in an array of strings
Xare contiguous. Therefore we pad each element of the C array with blanks and
Xstrip out C's trailing '\0'. After returning from the routine, we reinsert the
Xtrailing '\0' and kill the trailing blanks in each element.
X
XSummary: STRING(V) arguments are blank padded during the call to the FORTRAN
Xroutine, but remain original in the C code. (P)STRINGV arguments are blank
Xpadded for the FORTRAN call, and after returning from FORTRAN trailing blanks
Xare stripped off.
X
X
XPVOID, as noted above, is used to declare that a function will be passed as an
Xargument. In order to perform the call, CFORTRAN must know the language of the
Xfunction to be passed, therefore the when passing C functions to FORTRAN
Xroutines use:
X
X    FORTRAN_ROUTINE( ...., C_FUNCTION(some_function), ...)
X
Xand similarly when passing a FORTRAN routine:
X
X    FORTRAN_ROUTINE( ...., FORTRAN_FUNCTION(some_function), ...)
X
X
XThis list of argument types is not neccessarily complete. CFORTRAN may be
Xexpanded to handle a new type not among the above.
X
XN.B. The FORTRAN routines are called using macro expansions, therefore the
Xusual caveats for expressions in arguments apply. The expressions to the
Xroutines may be evaluated more than once, leading to lower performance and in
Xthe worst case bizzare bugs.
X
X
Xii) Calling C routines from FORTRAN:
X    --------------------------------
X
XNote that each of the following two statements to export a C routine to FORTRAN
Xcreate FORTRAN 'wrappers', written in C, which must be compiled and linked
Xalong with the original C routines and with the FORTRAN calling code.
X
XVAX VMS user's will have to redefine the one of the macros fcallsc or ccallsc.
XSee the examples or existing applications for details and information.
X
XFCALLSCSUBn(routine_name, argtype_1, ..., argtype_n)
X
Xor
X
XFCALLSCFUNn(routine_type, routine_name, argtype_1, ..., argtype_n)
X
XWhere:
X'n' = 0->7 (easily expanded to >7) stands for the number of arguments to the
X    routine.
Xroutine_name = the FORTRAN name of the routine (IN lowercase LETTERS).
Xroutine_type = the type of argument returned by C functions.
X             = DOUBLE, FLOAT, INT, LOGICAL, LONG, STRING.
Xargtype_i    = the type of argument passed to the FORTRAN routine and must be
X               consistent in the definition and prototyping of the routine
X             = DOUBLE, FLOAT, INT, LOGICAL, LONG, STRING, STRINGV.
X               For arrays or for routines changing the values of any of their
X                arguments; the C routines expect pointers to these arguments,
X                so the keywords are prepended by a 'P'.
X             = PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSTRING, PSTRINGV,
X               PVOID.
X               The keyword PVOID is a generic form of the nonSTRING types.
X               STRINGV refers to vector of strings.
X
X
X(P)STRING arguments have any trailing blanks removed before being passed to C,
Xthe same holds true for each element in (P)STRINGV. Space is malloc'd in all
Xcases big enough to hold the original string (elements) as well as C's
Xterminatinng '\0'. i.e. The useful size of the string (elements) is the same in
Xboth languages. PSTRING(V) => the string (elements) will be copied from the
Xmalloc'd space back into the FORTRAN bytes.
X
XTHE FOLLOWING APPLIES TO THE UNIX COMPILERS ONLY:
X                             ----
X(P)STRINGV for UNIX only: CFORTRAN cannot convert the FORTRAN vector of STRINGS
Xto the required C vector of STRINGS without explicitly knowing the number of
Xelements in the vector. The application must do one of the following for each
X(P)STRINGV argument in a routine before that routine's FCALLSCFUNn/SUBn is
Xcalled:
X
X#define routine_name_STRV_Ai NUM_ELEMS(j)
X or
X#define routine_name_STRV_Ai NUM_ELEM_ARG(k)
X or
X#define routine_name_STRV_Ai TERM_CHARS(l,m)
X
Xwhere: routine_name     is as above.
X       i [i=1->n.]      specifies the argument number of a STRING VECTOR.
X       j                would specify a fixed number of elements.
X       k [k=1->n. k!=i] would specify an integer argument which specifies the
X                        number of elements.
X       l [char]         the terminating character at the beginning of an
X                        element, indicating to cfortran that the preceeding
X                        elements in the vector are the valid ones.
X       m [m=1-...]      the number of terminating characters required to appear
X                        at the beginning of the terminating string element.
X                        Note that the terminating element is NOT possed on to
X                        the C routine.
X
Xe.g.
XCFORTRAN will pass on all elements, in the 1st and only argument to the C
Xroutine ce, of the STRING VECTOR until, but not including, the first string
Xelement beginning with 2 blank, ' ', characters.
X
X#define ce_STRV_A1 TERM_CHARS(' ',2)
XFCALLSCSUB1(ce,STRINGV)
X
XAgain the lists of types are not neccessarily complete. CFORTRAN may be
Xexpanded to handle a new type not among the above.
X
X
Xiii) Using C to manipulate FORTRAN COMMON BLOCKS:
X     -------------------------------------------------------
X
XFORTRAN common blocks are set up with the following construct:
X
X#define COMMON_BLOCK_NAME COMMON_BLOCK(common_block_name)
X
Xwhere common_block_name is given in the case shown. This construct exists to
Xensure that C code accessing the common block is machine independant.
X
X
XC programs can place a string (or a multidimensional array of strings) into a
XFORTRAN common block using the following call:
X
XC2FCBSTR( CSTR, FSTR, DIMENSIONS);
X
Xwhere:
X
XCSTR is a pointer to the first element of C's copy of the string (array).
X     The C code must use a duplicate of, not the original, common block string,
X     because the FORTRAN common block does not allocate space for C strings'
X     terminating '\0'.
X
XFSTR is a pointer to the first element of the string (array) in the common
X     block.
X
XDIMENSIONS is the number of dimensions of string array.
X     e.g. char a[10]      has DIMENSIONS=0.
X          char aa[10][17] has DIMENSIONS=1.
X          etc...
X
XC2FCBSTR will copy the string (array) from CSTR to FSTR, padding with blanks,
X' ', the trailing characters as required. C2FCBSTR uses DIMENSIONS and FSTR to
Xdetermine the lengths of the individual string elements and the total number of
Xelements in the string array.
X
XNote that:
X- the number of string elements in CSTR and FSTR are identical.
X- for arrays of strings, the useful lengths of strings in CSTR and FSTR must be
X  the same. i.e. CSTR elements each have 1 extra character to accomodate the
X  terminating '\0'.
X
X
XFCB2CSTR( FSTR, CSTR, DIMENSIONS)
X
Xis the inverse of C2FCBSTR, and shares the same arguments and caveats. Note
Xthat FCB2CSTR copies each string element of FSTR to CSTR, minus FORTRAN
Xstrings' trailing blanks.
X
X
XCFORTRAN USERS ARE STRONGLY URGED TO EXAMINE THE COMMON BLOCK EXAMPLES IN
XCFORTEST.C AND CFORTEX.FOR. The use of strings in common blocks is
Xdemonstrated, along with a suggested way for C to imitate FORTRAN EQUIVALENCE'd
Xvariables.
X
X
X              ===> USER'S OF CFORTRAN NEED READ NO FURTHER <===
X
X
XIII Some Details of and Comments on CFORTRAN
X--------------------------------------------
X
XThe following notes should be useful to those wishing to port CFORTRAN to new
Xtypes of machines.
X
X
XCFORTRAN.H consist of about 1000 lines of source code. Only about 300 lines of
XCFORTRAN.H are interesting, the rest are slightly modified 'repeats'. Porting
XCFORTRAN applications, e.g. the hbook.h and cstring.c mentioned above, to
Xother machines is trivial.  hbook.h is machine independant, and cstring.c will
Xat most need to have the 'fcallsc' macro redefined. Porting CFORTRAN itself
Xrequires a solid knowledge of the new machines C preprocessor, and its FORTRAN
Xargument passing mechanisms. Logically CFORTRAN exists as two halves, a "C
XCALLS FORTRAN" and a "FORTRAN CALLS C" utility. In some cases it may be
Xperfectly reasonable to port only 'one half' of CFORTRAN onto a new system.
X
X
XCFORTRAN is simple enough to be used by the most basic of applications, i.e.
Xmaking a single C/FORTRAN routine available to the FORTRAN/C programmers. Yet
XCFORTRAN is powerful enough to easily make entire C/FORTRAN libraries available
Xto FORTRAN/C programmers.
X
X
XCFORTRAN is the ideal tool for FORTRAN libraries which are being rewritten in
XC. It allows the routines to be written in 'natural C', without having to
Xconsider the FORTRAN argument passing mechanisms of any machine. It also allows
XC code accessing these rewritten routines, to use the C entry point. Without
XCFORTRAN one could fall into the perverse practice of C code calling a C
Xfunction using FORTRAN argument passing mechanisms!
X
X
XPerhap the philosophy and mechanisms of CFORTRAN could be used and extended
Xto create other language bridges such as ADAFORTRAN, CPASCAL, COCCAM, etc.
X
X
X
XIV Pros, Cons and Improvements to CFORTRAN
X------------------------------------------
X
XThe C calls FORTRAN half is all pro. A list would include:
X
Xi) Machine independant and C or FORTRAN independant calls to FORTRAN code.
Xe.g. C      :       hbook1(1,"pT spectrum of pi+",100,0.,5.,0.);
X     FORTRAN:  call hbook1(1,'pT spectrum of pi+',100,0.,5.,0.)
Xii) Non-STRING(V) arguments have no, or at most one assignment as overhead.
Xiii) 'Input only' arguments are protected by using an intermediate value.
Xiv) I don't think STRING(V)'s can be handled much faster, even in individually
Xtuned routines.
X
X
XThe FORTRAN calls C half has the fundamental inelegancy of using an
Xintermediate function. Perhaps a preprocessor and those %DEF (?) FORTRAN
Xextensions could help. I don't know, I'm just a C programmer who wants to use
Xroutines written in FORTRAN.
X
X
XIt might make sense to have separate CFORTRAN and FORTRANC utilities, but I've
Xleft them tied together for the moment.
X
X
XUsing FCALLSCFUNn and CCALLSFFUNn for a function in the same source code, i.e.
Xcreating the FORTRAN entry to a C function and then allowing C to call this
XFORTRAN entry, obviously serves only test purposes. Note that the order given
Xabove is a must, and that a compiler warning is generated because the FORTRAN
Xfunction prototype generated by CCALLSFFUNn does not match the entry point
Xcreated by FCALLSCFUNn. This might be fixable, see CFORTRAN.H, but since these
Xcombo.'s are used in tests only, I don't think it's worth it. I say might
Xbecause I'm not sure one can satisfy the case sensitive compiler here.
X
X
X
XV Machine Dependancies of CFORTRAN
X----------------------------------
X
XI leave it to the lucky programmer porting CFORTRAN to a new machine, to
Xdiscover the FORTRAN argument passing mechanisms. A safe starting point is to
Xassume that variables and arrays are simply passed by reference as they are in
XVAX VMS and UNIX, but I make no guarantees. Strings, and n-dimensional arrays
Xof strings are a different story. I doubt that any systems do it quite like VAX
XVMS does it, so that the UNIX version may provide an easier starting point.
X
X
XCFORTRAN uses and abuses the ## operator. Although the ## operator proper does
Xnot exist in  VAX VMS nor in MIPS C, a kludge does; /**/ with no space allowed
Xbetween the slashes, '/', and the macros or tags one wishes to concatenate. e.g.
X#define concat(a,b) a/**/b   /* works*/
Xmain()
X{
X  concat(pri,ntf)("hello");           /* e.g. */
X}
XN.B. I have learnt of an alternate kludge to /**/ which could replace ##.
XOn some compilers without ##, /**/ may also not work, this new kludge may be a
Xway out. For more info., porters of CFORTRAN should contact me.
X
X
X
XVI Machine Dependancies of CFORTRAN Applications
X------------------------------------------------
X
XThe only machine dependancy of CFORTRAN Applications I know of are the names of
Xroutines written in C to be called by FORTRAN. This problem arises under VAX
XVMS because the 'interpreter' routine, written in C and called by the FORTRAN
Xcode, needs an object code name for itself different from that of the original
XC routine it will try to invoke.
X
XThis problem does not exist with some FORTRAN compilers. E.g. MIPS' f77
Xappends  each FORTRAN module name with a single underscore, '_', character.
XHence, if all C interpreter routines are prepended with this '_', all is well.
XA similar solution may exist when a case sensitive linker is available.
X
XFor other compilers, which leave the FORTRAN name as the module name, there
Xexist only two situations.
Xi)  If the C source code for the routines is NOT available, the calls to
X    the C routine from FORTRAN must use a different name. In fortran.h the
X    'fcallsc' [f-calls-c] macro exists to modify the names of the interpreter
X    routines in a consistent manner.
Xii) If the C source code does exist, a decision for one of the two following
X    possible resolutions has to be made.
X    a) The source code is left alone and an identical approach to i) above is
X       taken. This might be preferable for smaller applications, where the
X       C expertise doesn't exist or has better things to do.
X    b) This is the better method in that it maintains absolute transparency
X       at the user level, unfortunately it is more complicated, but with care
X       it is just as robust at the user level. In short, the objects compiled
X       from the original C modules are renamed. This is done in the header
X       file prototyping the original C routines code. Unfortunately this
X       translation also has to be done when C code calls the C routine. Since
X       the name modification is done in the routines header file, it's hidden
X       from the C user, unless they carefully examines the libraries and/or
X       object code. In CFORTRAN.H the 'ccallsc' [c-calls-c] macro exists to
X       modify the names of the original routines in a consistent manner.
X
X
X
X
XTHIS SOFTWARE IS PUBLIC DOMAIN. IT MAY BE FREELY COPIED AND USED EVERYWHERE. IT
XMAY BE DISTRIBUTED WITH NON-COMMERCIAL PRODUCTS, ASSUMING PROPER CREDIT TO THE
XAUTHOR IS GIVEN, BUT IT SHOULD NOT BE RESOLD. IF YOU WANT TO DISTRIBUTE THE
XSOFTWARE WITH A COMMERCIAL PRODUCT, CONTACT THE AUTHOR.
XTHIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
XEXPRESSED OR IMPLIED. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
XSOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST
XOF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
X
XVAX VMS, Silicon Graphics (SGI), DECstations, Mips RISC and IBM RS/6000
Xare registered trademarks.
X
X/* end: cfortran.doc */
END_OF_FILE
  if test 27512 -ne `wc -c <'cfortran.doc'`; then
    echo shar: \"'cfortran.doc'\" unpacked with wrong size!
  fi
  # end of 'cfortran.doc'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.