The following sections provide example programs that show the use of traceback to locate the cause of the error:
Example: End-of-File Condition, Program teof
In the following example, a READ statement creates an End-Of-File error, which the application has not handled:
program teof
integer*4 i,res
i=here( )
end
integer*4 function here( )
here = we( )
end
integer*4 function we( )
we = go( )
end
integer*4 function go( )
go = again( )
end
integer*4 function again( )
integer*4 a
open(10,file='xxx.dat',form='unformatted',status='unknown')
read(10) a
again=a
end
The diagnostic output that results when this program is built with traceback enabled and linked against the single-threaded, DLL Fortran run-time library on the ia32 platform:
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat
Image PC Routine Line Source
DFORRT.dll 1000A3B2 Unknown Unknown Unknown
DFORRT.dll 1000A184 Unknown Unknown Unknown
DFORRT.dll 10009324 Unknown Unknown Unknown
DFORRT.dll 10009596 Unknown Unknown Unknown
DFORRT.dll 10024193 Unknown Unknown Unknown
teof.exe 004011A9 AGAIN 21 teof.for
teof.exe 004010DD GO 15 teof.for
teof.exe 004010A7 WE 11 teof.for
teof.exe 00401071 HERE 7 teof.for
teof.exe 00401035 TEOF 3 teof.for
teof.exe 004013D9 Unknown Unknown Unknown
teof.exe 004012DF Unknown Unknown Unknown
KERNEL32.dll 77F1B304 Unknown Unknown Unknown
The first line of the output is the standard Fortran run-time error message. What follows is the result of walking the call stack in reverse order to determine where the error originated. Each line of output represents a call frame on the stack. Since the application was compiled with /traceback, the PC's that fall in Fortran code are correlated to their matching routine name, line number and source module. PC's which are not in Fortran code are not correlated and are reported as "Unknown."
The first five frames show the calls to routines in the Fortran run-time library (in reverse order). Since the application was linked against the single threaded DLL version of the library, the image name reported is DFORRT.dll. These are the run-time routines that were called to do the READ and upon detection of the EOF condition, were invoked to report the error. In the case of an unhandled I/O programming error, there will always be a few frames on the call stack down in run-time code like this.
The stack frame of real interest to the Fortran developer is the first frame in image teof.exe which shows that the error originated in the routine named AGAIN in source module teof.for at line 21. Looking in the source code at line 21, we see the Fortran READ statement that incurred the end-of-file condition.
The next four frames show that completes the trail of calls in the Fortran user code that led to the routine that got the error (TEOF->HERE->WE->GO->AGAIN).
Finally, the bottom three frames are routines which handled the startup and initialization of the program.
If this program had been linked against the single-threaded, static Fortran run-time library, the output would then look like:
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat
Image PC Routine Line Source
teof.exe 004067D2 Unknown Unknown Unknown
teof.exe 0040659F Unknown Unknown Unknown
teof.exe 00405754 Unknown Unknown Unknown
teof.exe 004059C5 Unknown Unknown Unknown
teof.exe 00403543 Unknown Unknown Unknown
teof.exe 004011A9 AGAIN 21 teof.for
teof.exe 004010DD GO 15 teof.for
teof.exe 004010A7 WE 11 teof.for
teof.exe 00401071 HERE 7 teof.for
teof.exe 00401035 TEOF 3 teof.for
teof.exe 004202F9 Unknown Unknown Unknown
teof.exe 00416063 Unknown Unknown Unknown
KERNEL32.dll 77F1B304 Unknown Unknown Unknown
Notice that the initial five stack frames now show routines in image teof.exe, not DFORRT.DLL. The routines are the same five run-time routines as previously reported for the DLL case but since the application was linked against the static Fortran run-time library (dfor.lib), the object modules containing these routines were linked into the application image (teof.exe). Using the map file, you can determine that the PC reported in the top stack frame, 004067D2, is from routine _for_stack_trace, in module for_diags.obj of library dfor.lib (004067a0 < PC=004067D2 < 004079f0):
...
0001:000057a0 _for_stack_trace 004067a0 f dfor:for_diags.obj
0001:000069f0 _for__find_trace_info_file 004079f0 f dfor:for_diags.obj
...
Now suppose the application was compiled without traceback enabled and once again, linked against the single-threaded, static Fortran library. The diagnostic output would then appear as follows:
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat
Image PC Routine Line Source
teof.exe 00406792 Unknown Unknown Unknown
teof.exe 0040655F Unknown Unknown Unknown
teof.exe 00405714 Unknown Unknown Unknown
teof.exe 00405985 Unknown Unknown Unknown
teof.exe 00403503 Unknown Unknown Unknown
teof.exe 00401169 Unknown Unknown Unknown
teof.exe 004010A8 Unknown Unknown Unknown
teof.exe 00401078 Unknown Unknown Unknown
teof.exe 00401048 Unknown Unknown Unknown
teof.exe 0040102F Unknown Unknown Unknown
teof.exe 004202B9 Unknown Unknown Unknown
teof.exe 00416023 Unknown Unknown Unknown
KERNEL32.dll 77F1B304 Unknown Unknown Unknown
Without the correlation information in the image that /traceback previously supplied, the Fortran run-time system cannot correlate PC's to routine name, line number, and source file. You can still use the map file to at least determine the routine names and what modules they are in. Look at the beginning of the entry point list in the map file for this image:
Address Publics by Value Rva+Base Lib:Object
0001:00000000 _TEOF 00401000 f teof.obj
0001:00000000 _TEOF@0 00401000 f teof.obj
0001:00000000 _MAIN__ 00401000 f teof.obj
0001:0000003d _HERE 0040103d f teof.obj
0001:0000003d _HERE@0 0040103d f teof.obj
0001:0000006d _WE@0 0040106d f teof.obj
0001:0000006d _WE 0040106d f teof.obj
0001:0000009d _GO 0040109d f teof.obj
0001:0000009d _GO@0 0040109d f teof.obj
0001:000000cd _AGAIN 004010cd f teof.obj
0001:000000cd _AGAIN@0 004010cd f teof.obj
0001:00000180 _for_rtl_init_ 00401180 f dfor:for_init.obj
...
After determining that the first five stack frames fall in run-time code (using portions of the map file not shown here), the sixth frame shows a PC of 00401169. Using the fragment of the map file shown above, it can be seen that this PC is greater than 004010cd but less than 00401180 and is therefore in routine _AGAIN, the first Fortran routine on the call stack. The remaining PC's can be manually correlated in a similar fashion to reconstruct the calling sequence.
Remember that compiling with /traceback increases the size of your application's image because of the extra PC correlation information included in the image. You can see if the extra traceback information is included in an image (checking for the presence of a .trace section) by typing:
link -dump -summary your_app.exe
For the teof.exe example, the following is displayed:
Microsoft (R) COFF Binary File Dumper Version x.xx.xxxx
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file teof.exe
File Type: EXECUTABLE IMAGE
Summary
1000 .data
1000 .idata
1000 .rdata
1000 .text
1000 .trace
Check the file size with a simple directory command. Here's the teof.exe example linked against the dynamic Fortran library with traceback:
03/03/98 01:45p 5,120 teof.exe
1 File(s) 5,120 bytes
Without traceback, the following appears:
03/03/98 01:46p 4,608 teof.exe
1 File(s) 4,608 bytes
For this simple example, the traceback correlation information added 512 bytes to the image size. In a real application, this would probably be much larger. For any application, the developer must decide if the increase in image size is worth the benefit of automatic PC correlation or if manually correlating PC's with a map file is acceptable.
For command-line use and in the release configuration in the visual development environment, traceback information is not included by default in Fortran compiles (default is /notraceback). In the visual development environment, the default is /traceback in the debug configuration. For the release configuration, request traceback in the Run Time category of the Project Settings dialog box.
If an error occurs when traceback was requested during compilation, the run-time library will produce the correlated call stack display.
If an error occurs when traceback was disabled during compilation, the run-time library will produce the uncorrelated call stack display.
If you do not want to see the call stack information displayed, you can set the environment variable FOR_DISABLE_STACK_TRACE to true. You will still get the Fortran run-time error message:
forrtl: severe (24): end-of-file during read, unit 10, file E:\USERS\xxx.dat
Example: Machine Exception Condition, Program ovf
The following program generates a floating-point overflow exception when compiled with /fpe:0:
program ovf
real*4 a
a=1e37
do i=1,10
a=hey(a)
end do
print *, 'a= ', a
end
real*4 function hey(b)
real*4 b
hey = watch(b)
end
real*4 function watch(b)
real*4 b
watch = out(b)
end
real*4 function out(b)
real*4 b
out = below(b)
end
real*4 function below(b)
real*4 b
below = b*10.0e0
end
When this program is compiled on an ia32 system with /traceback, /fpe:0, and /optimization:0, the traceback output appears as follows:
forrtl: error (72): floating overflow
Image PC Routine Line Source
ovf.exe 00401161 BELOW 29 ovf.f90
ovf.exe 0040113C OUT 24 ovf.f90
ovf.exe 0040111B WATCH 19 ovf.f90
ovf.exe 004010FA HEY 14 ovf.f90
ovf.exe 0040105B OVF 7 ovf.f90
ovf.exe 00432429 Unknown Unknown Unknown
ovf.exe 00426C74 Unknown Unknown Unknown
KERNEL32.dll 77F1B9EA Unknown Unknown Unknown
Notice that unlike the previous example of an unhandled I/O programming error, the stack walk can begin right at the point of the exception. There are no run-time routines on the call stack to dig through. The overflow occurs in routine BELOW at PC 00401161 which is correlated to line 29 of the source file ovf.f90.
When the program is compiled at a higher optimization level, /optimization:4, with /fpe:0 and /traceback, the traceback output appears as follows:
forrtl: error (72): floating overflow
Image PC Routine Line Source
ovf.exe 00401070 OVF 29 ovf.f90
ovf.exe 004323E9 Unknown Unknown Unknown
ovf.exe 00426C34 Unknown Unknown Unknown
KERNEL32.dll 77F1B9EA Unknown Unknown Unknown
With /optimize:4, the entire program has been inlined. We can see this with a quick look in the listing file:
...
.CODE
PUBLIC _MAIN__
0000 _MAIN__ PROC
55 0000 push ebp
EC8B 0001 mov ebp, esp
30EC83 0003 sub esp, 48
000000E8 0006 call _for_check_flawed_pentium@0
00
04EC83 000B sub esp, 4
0020058D 000E lea eax, dword ptr .literal$+32
0000
50 0014 push eax
000000E8 0015 call _for_set_fpe_@4
00
001C058D 001A lea eax, dword ptr .literal$+28
0000
50 0020 push eax
000000E8 0021 call _for_set_reentrancy@4
00
04C483 0026 add esp, 4
001805D9 0029 fld dword ptr .literal$+24 ; 000029
0000
00000DD8 002F fmul dword ptr .literal$
0000
9B 0035 fwait
00000DD8 0036 fmul dword ptr .literal$
0000
9B 003C fwait
00000DD8 003D fmul dword ptr .literal$
0000
9B 0043 fwait
00000DD8 0044 fmul dword ptr .literal$
0000
9B 004A fwait
00000DD8 004B fmul dword ptr .literal$
0000
9B 0051 fwait
00000DD8 0052 fmul dword ptr .literal$
0000
9B 0058 fwait
00000DD8 0059 fmul dword ptr .literal$
0000
9B 005F fwait
00000DD8 0060 fmul dword ptr .literal$
0000
9B 0066 fwait
00000DD8 0067 fmul dword ptr .literal$
0000
FC5DD9 006D fstp dword ptr -4[ebp]
9B 0070 fwait
D233 0071 xor edx, edx ; 000009
0014058D 0073 lea eax, dword ptr .literal$+20
0000
03D045C7 0079 mov dword ptr -48[ebp], 3
000000
D44589 0080 mov dword ptr -44[ebp], eax
000C0D8D 0083 lea ecx, dword ptr .literal$+12
0000
DC458D 0089 lea eax, .T1_ ; eax, dword ptr -36[ebp]
DC5589 008C mov .T1_, edx ; dword ptr -36[ebp], edx
04EC83 008F sub esp, 4
D0558D 0092 lea edx, dword ptr -48[ebp]
52 0095 push edx
51 0096 push ecx
84FF0068 0097 push 126156544
07
FFFFFF68 009C push -1
FF
50 00A1 push eax
000000E8 00A2 call _for_write_seq_lis
00
18C483 00A7 add esp, 24
FC458B 00AA mov eax, dword ptr -4[ebp]
D04589 00AD mov dword ptr -48[ebp], eax
04EC83 00B0 sub esp, 4
D0558D 00B3 lea edx, dword ptr -48[ebp]
00040D8D 00B6 lea ecx, dword ptr .literal$+4
0000
DC458D 00BC lea eax, .T1_ ; eax, dword ptr -36[ebp]
52 00BF push edx
51 00C0 push ecx
50 00C1 push eax
000000E8 00C2 call _for_write_seq_lis_xmit
00
10C483 00C7 add esp, 16
E58B 00CA mov esp, ebp ; 000010
000001B8 00CC mov eax, 1
00
5D 00D1 pop ebp
C3 00D2 ret
_MAIN__ ENDP
...
The main program, OVF, no longer calls routine HEY. While the output is not quite what one might have expected intuitively, it is still entirely correct. You need to keep in mind the effects of compiler optimization when you interpret the diagnostic information reported for a failure in a release image.
If the same image were executed again but with environment variable FOR_ENABLE_VERBOSE_STACK_TRACE set to true, you would also see a dump of the exception context record at the time of the error. Here is an excerpt of how that would appear on an ia32 system:
forrtl: error (72): floating overflow
Hex Dump Of Exception Record Context Information:
Exception Context: Processor Control and Status Registers.
EFlags: 00010212
CS: 0000001B EIP: 00401161 SS: 00000023 ESP: 0012FE38 EBP: 0012FE60
Exception Context: Processor Integer Registers.
EAX: 00444488 EBX: 00000009 ECX: 00444488 EDX: 00000002
ESI: 0012FBBC EDI: F9A70030
Exception Context: Processor Segment Registers.
DS: 00000023 ES: 00000023 FS: 00000038 GS: 00000000
Exception Context: Floating Point Control and Status Registers.
ControlWord: FFFF0262 ErrorOffset: 0040115E DataOffset: 0012FE5C
StatusWord: FFFFF8A8 ErrorSelector: 015D001B DataSelector: FFFF0023
TagWord: FFFF3FFF Cr0NpxState: 00000000
Exception Context: Floating Point RegisterArea.
RegisterArea[00]: 4080BC143F4000000000 RegisterArea[10]: F7A0FFFFFFFF77F9D860
RegisterArea[20]: 00131EF0000800060012 RegisterArea[30]: 00000012F7C002080006
RegisterArea[40]: 02080006000000000000 RegisterArea[50]: 0000000000000012F7D0
RegisterArea[60]: 00000000000000300000 RegisterArea[70]: FBBC000000300137D9EF
...
Example: Using Traceback in Mixed Fortran/C Applications, Program FPING and CPONG
Consider the following example that shows how the traceback output might appear in a mixed Fortran/C application. The main program is a Fortran program named FPING. Program FPING triggers a chain of function calls which are alternately Fortran and C code. Eventually, the C routine named Unlucky is called, which produces a floating divide by zero error.
Source module FPING.FOR contains the Fortran function definitions, each of which calls a C routine from source module CPONG.C. FPING.FOR is compiled with the /fpe:0 /optimize:0 /traceback options enabled, on the ia32 platform. Here's the program traceback output:
forrtl: error (73): floating divide by zero
Image PC Routine Line Source
fping.exe 00401161 Unknown Unknown Unknown
fping.exe 004010DC DOWN4 58 fping.for
fping.exe 0040118F Unknown Unknown Unknown
fping.exe 004010B6 DOWN3 44 fping.for
fping.exe 00401181 Unknown Unknown Unknown
fping.exe 00401094 DOWN2 31 fping.for
fping.exe 00401173 Unknown Unknown Unknown
fping.exe 00401072 DOWN1 18 fping.for
fping.exe 0040104B FPING 5 fping.for
fping.exe 004013B9 Unknown Unknown Unknown
fping.exe 004012AF Unknown Unknown Unknown
KERNEL32.dll 77F1B304 Unknown Unknown Unknown
Notice that the stack frames contributed by Fortran routines can be correlated to a routine name, line number, and source module but those frames contributed by C routines cannot be correlated. Remember, even though the stack can be walked in reverse, and PC's reported, the information necessary to correlate the PC to a routine name, line number, and so on, is contributed to the image from the objects generated by the Fortran compiler. The C compiler does not have this capability. Also remember that you only get the correlation information if you specify the /traceback option for your Fortran compiles.
The top stack frame cannot be correlated to a routine name because it is in C code. By examining the map file for the application, we can see that the reported PC, 00401161, is greater than the start of routine _Unlucky, but less than the start of routine _down1_C, so we at least know the error occurred in routine _Unlucky. Here is the pertinent section of the map file:
Address Publics by Value Rva+Base Lib:Object
0001:00000000 _FPING 00401000 f fping.obj
0001:00000000 _FPING@0 00401000 f fping.obj
0001:00000000 _MAIN__ 00401000 f fping.obj
0001:0000005f _DOWN1 0040105f f fping.obj
0001:0000005f _DOWN1@4 0040105f f fping.obj
0001:00000083 _DOWN2@4 00401083 f fping.obj
0001:00000083 _DOWN2 00401083 f fping.obj
0001:000000a5 _DOWN3 004010a5 f fping.obj
0001:000000a5 _DOWN3@4 004010a5 f fping.obj
0001:000000c7 _DOWN4@4 004010c7 f fping.obj
0001:000000c7 _DOWN4 004010c7 f fping.obj
0001:00000100 _Fact 00401100 f cpong.obj
0001:00000127 _Pythagoras 00401127 f cpong.obj
******************************************************
The reported PC lies between the start of _Unlucky and
the start of _down1_C...
******************************************************
0001:0000014d _Unlucky 0040114d f cpong.obj
0001:00000167 _down1_C 00401167 f cpong.obj
0001:00000175 _down2_C 00401175 f cpong.obj
0001:00000183 _down3_C 00401183 f cpong.obj
0001:00000192 _for_check_flawed_pentium@0 00401192 f dfordll:DFORRT.dll
0001:00000198 _for_set_fpe_@4 00401198 f dfordll:DFORRT.dll
0001:0000019e _for_set_reentrancy@4 0040119e f dfordll:DFORRT.dll
etc...
In a similar manner, the other PC's reported as "Unknown" can be correlated to a routine name using the map file.
When examining traceback output (or any type of diagnostic output for that matter), it is always important to keep in mind the affects of compiler optimization. The Fortran source module in the above example was built with optimization turned off, /optimize:0. Look at the output when optimizations are enabled, /optimize:4:
forrtl: error (73): floating divide by zero
Image PC Routine Line Source
fping.exe 00401111 Unknown Unknown Unknown
fping.exe 0040109D DOWN4 58 fping.for
fping.exe 0040113F Unknown Unknown Unknown
fping.exe 00401082 DOWN3 44 fping.for
fping.exe 00401131 Unknown Unknown Unknown
fping.exe 0040106B DOWN2 31 fping.for
fping.exe 00401123 Unknown Unknown Unknown
fping.exe 00401032 FPING 18 fping.for
fping.exe 00401369 Unknown Unknown Unknown
fping.exe 0040125F Unknown Unknown Unknown
KERNEL32.dll 77F1B304 Unknown Unknown Unknown
From the traceback output, it would appear that routine DOWN1 was never called. In fact, it has not been called. At the higher optimization level, the compiler has inlined function DOWN1 so that the call to routine down1_C is now made from FPING. The correlated line number still points to the correct line in the source code. You can see that DOWN1 was inlined by looking in the listing file, FPING.LST:
.CODE
PUBLIC _MAIN__
0000 _MAIN__ PROC
55 0000 push ebp
EC8B 0001 mov ebp, esp
04EC83 0003 sub esp, 4
53 0006 push ebx
000000E8 0007 call _for_check_flawed_pentium@0
00
04EC83 000C sub esp, 4
0008058D 000F lea eax, dword ptr .literal$+8
0002
50 0015 push eax
000000E8 0016 call _for_set_fpe_@4
00
0004058D 001B lea eax, dword ptr .literal$+4
0002
50 0021 push eax
000000E8 0022 call _for_set_reentrancy@4
00
000035FF 0027 push dword ptr .literal$ ; 000018
0000
000035FF 0027 push dword ptr .literal$ ; 000018
0000
*******************************************************************
Call _down1_C from MAIN__ here, no call to DOWN1 Fortran routine...
*******************************************************************
000000E8 002D call _down1_C
00
C0DD 0032 ffree st(0)
F7D9 0034 fincstp
08C483 0036 add esp, 8
000001B8 0039 mov eax, 1 ; 000006
A0
5B 003E pop ebx
E58B 003F mov esp, ebp
5D 0041 pop ebp
C3 0042 ret
_MAIN__ ENDP
Finally, suppose the example Fortran code is redesigned with each of the Fortran routines split into separate source modules. Here is what the traceback output would look like with the redesigned code:
forrtl: error (73): floating divide by zero
Image PC Routine Line Source
fpingmain.exe 00401171 Unknown Unknown Unknown
fpingmain.exe 004010ED DOWN4 12 fping4.for
fpingmain.exe 0040119F Unknown Unknown Unknown
fpingmain.exe 004010C1 DOWN3 11 fping3.for
fpingmain.exe 00401191 Unknown Unknown Unknown
fpingmain.exe 00401099 DOWN2 11 fping2.for
fpingmain.exe 00401183 Unknown Unknown Unknown
fpingmain.exe 00401073 DOWN1 11 fping1.for
fpingmain.exe 0040104B FPING 5 fpingmain.for
fpingmain.exe 004013C9 Unknown Unknown Unknown
fpingmain.exe 004012BF Unknown Unknown Unknown
KERNEL32.dll 77F1B304 Unknown Unknown Unknown
Notice that the line number and source file correlation information has changed to reflect the new design of the code.
Here are the sources used in the above examples:
************************************
FPING.FOR
************************************
program fping
real*4 a,b
a=-10.0
b=down1(a)
end
real*4 function down1(b)
real*4 b
!DEC$ IF DEFINED(_X86_)
INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'_down1_C'] (n)
!DEC$ ELSE
INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'down1_C'] (n)
!DEC$ ENDIF
REAL*4 n [VALUE]
END
real*4 down1_C
down1 = down1_C(b)
end
real*4 function down2(b)
real*4 b [VALUE]
!DEC$ IF DEFINED(_X86_)
INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'_down2_C'] (n)
!DEC$ ELSE
INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'down2_C'] (n)
!DEC$ ENDIF
REAL*4 n [VALUE]
END
real*4 down2_C
down2 = down2_C(b)
end
real*4 function down3(b)
real*4 b [VALUE]
!DEC$ IF DEFINED(_X86_)
INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'_down3_C'] (n)
!DEC$ ELSE
INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'down3_C'] (n)
!DEC$ ENDIF
REAL*4 n [VALUE]
END
real*4 down3_C
down3 = down3_C(b)
end
real*4 function down4(b)
real*4 b [VALUE]
!DEC$ IF DEFINED(_X86_)
INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'_Unlucky'] (a,c)
!DEC$ ELSE
INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'Unlucky'] (a,c)
!DEC$ ENDIF
REAL*4 a [VALUE]
REAL*4 c [REFERENCE]
END
real*4 a
call Unlucky(b,a)
down4 = a
end
************************************
CPONG.C
************************************
#include <math.h>
extern float __stdcall DOWN2 (float n);
extern float __stdcall DOWN3 (float n);
extern float __stdcall DOWN4 (float n);
int Fact( int n )
{
if (n > 1)
return( n * Fact( n - 1 ));
return 1;
}
void Pythagoras( float a, float b, float *c)
{
*c = sqrt( a * a + b * b );
}
void Unlucky( float a, float *c)
{
float b=0.0;
*c = a/b;
}
float down1_C( float a )
{
return( DOWN2( a ));
}
float down2_C( float a )
{
return( DOWN3( a ));
}
float down3_C( float a )
{
return( DOWN4( a ));
}
************************************
FPINGMAIN.FOR
************************************
program fping
real*4 a,b
a=-10.0
b=down1(a)
end
************************************
FPING1.FOR
************************************
real*4 function down1(b)
real*4 b
!DEC$ IF DEFINED(_X86_)
INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'_down1_C'] (n)
!DEC$ ELSE
INTERFACE TO REAL*4 FUNCTION down1_C [C,ALIAS:'down1_C'] (n)
!DEC$ ENDIF
REAL*4 n [VALUE]
END
real*4 down1_C
down1 = down1_C(b)
end
************************************
FPING2.FOR
************************************
real*4 function down2(b)
real*4 b [VALUE]
!DEC$ IF DEFINED(_X86_)
INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'_down2_C'] (n)
!DEC$ ELSE
INTERFACE TO REAL*4 FUNCTION down2_C [C,ALIAS:'down2_C'] (n)
!DEC$ ENDIF
REAL*4 n [VALUE]
END
real*4 down2_C
down2 = down2_C(b)
end
************************************
FPING3.FOR
************************************
real*4 function down3(b)
real*4 b [VALUE]
!DEC$ IF DEFINED(_X86_)
INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'_down3_C'] (n)
!DEC$ ELSE
INTERFACE TO REAL*4 FUNCTION down3_C [C,ALIAS:'down3_C'] (n)
!DEC$ ENDIF
REAL*4 n [VALUE]
END
real*4 down3_C
down3 = down3_C(b)
end
************************************
FPING4.FOR
************************************
real*4 function down4(b)
real*4 b [VALUE]
!DEC$ IF DEFINED(_X86_)
INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'_Unlucky'] (a,c)
!DEC$ ELSE
INTERFACE TO SUBROUTINE Unlucky [C,ALIAS:'Unlucky'] (a,c)
!DEC$ ENDIF
REAL*4 a [VALUE]
REAL*4 c [REFERENCE]
END
real*4 a
call Unlucky(b,a)
down4 = a
end