g77_18.txt

(32 KB) Pobierz
Go to the first, previous, next, last section, table of contents.

----------------------------------------------------------------------------

Debugging and Interfacing

GNU Fortran currently generates code that is object-compatible with the f2c
converter. Also, it avoids limitations in the current GBE, such as the
inability to generate a procedure with multiple entry points, by generating
code that is structured differently (in terms of procedure names, scopes,
arguments, and so on) than might be expected.

As a result, writing code in other languages that calls on, is called by, or
shares in-memory data with g77-compiled code generally requires some
understanding of the way g77 compiles code for various constructs.

Similarly, using a debugger to debug g77-compiled code, even if that
debugger supports native Fortran debugging, generally requires this sort of
information.

This section describes some of the basic information on how g77 compiles
code for constructs involving interfaces to other languages and to
debuggers.

Caution: Much or all of this information pertains to only the current
release of g77, sometimes even to using certain compiler options with g77
(such as `-fno-f2c'). Do not write code that depends on this information
without clearly marking said code as nonportable and subject to review for
every new release of g77. This information is provided primarily to make
debugging of code generated by this particular release of g77 easier for the
user, and partly to make writing (generally nonportable) interface code
easier. Both of these activities require tracking changes in new version of
g77 as they are installed, because new versions can change the behaviors
described in this section.

Main Program Unit (PROGRAM)

When g77 compiles a main program unit, it gives it the public procedure name
`MAIN__'. The libf2c library has the actual main() procedure as is typical
of C-based environments, and it is this procedure that performs some initial
start-up activity and then calls `MAIN__'.

Generally, g77 and libf2c are designed so that you need not include a main
program unit written in Fortran in your program--it can be written in C or
some other language. Especially for I/O handling, this is the case, although
g77 version 0.5.16 includes a bug fix for libf2c that solved a problem with
using the OPEN statement as the first Fortran I/O activity in a program
without a Fortran main program unit.

However, if you don't intend to use g77 (or f2c) to compile your main
program unit--that is, if you intend to compile a main() procedure using
some other language--you should carefully examine the code for main() in
libf2c, found in the source file `gcc/f/runtime/libF77/main.c', to see what
kinds of things might need to be done by your main() in order to provide the
Fortran environment your Fortran code is expecting.

For example, libf2c's main() sets up the information used by the IARGC and
GETARG intrinsics. Bypassing libf2c's main() without providing a substitute
for this activity would mean that invoking IARGC and GETARG would produce
undefined results.

When debugging, one implication of the fact that main(), which is the place
where the debugged program "starts" from the debugger's point of view, is in
libf2c is that you won't be starting your Fortran program at a point you
recognize as your Fortran code.

The standard way to get around this problem is to set a break point (a
one-time, or temporary, break point will do) at the entrance to `MAIN__',
and then run the program. A convenient way to do so is to add the gdb
command

tbreak MAIN__

to the file `.gdbinit' in the directory in which you're debugging (using
gdb).

After doing this, the debugger will see the current execution point of the
program as at the beginning of the main program unit of your program.

Of course, if you really want to set a break point at some other place in
your program and just start the program running, without first breaking at
`MAIN__', that should work fine.

Procedures (SUBROUTINE and FUNCTION)

Currently, g77 passes arguments via reference--specifically, by passing a
pointer to the location in memory of a variable, array, array element, a
temporary location that holds the result of evaluating an expression, or a
temporary or permanent location that holds the value of a constant.

Procedures that accept CHARACTER arguments are implemented by g77 so that
each CHARACTER argument has two actual arguments.

The first argument occupies the expected position in the argument list and
has the user-specified name. This argument is a pointer to an array of
characters, passed by the caller.

The second argument is appended to the end of the user-specified calling
sequence and is named `__g77_length_x', where x is the user-specified name.
This argument is of the C type ftnlen (see `gcc/f/runtime/f2c.h.in' for
information on that type) and is the number of characters the caller has
allocated in the array pointed to by the first argument.

A procedure will ignore the length argument if `X' is not declared
CHARACTER*(*), because for other declarations, it knows the length. Not all
callers necessarily "know" this, however, which is why they all pass the
extra argument.

The contents of the CHARACTER argument are specified by the address passed
in the first argument (named after it). The procedure can read or write
these contents as appropriate.

When more than one CHARACTER argument is present in the argument list, the
length arguments are appended in the order the original arguments appear. So
`CALL FOO('HI','THERE')' is implemented in C as `foo("hi","there",2,5);',
ignoring the fact that g77 does not provide the trailing null bytes on the
constant strings (f2c does provide them, but they are unnecessary in a
Fortran environment, and you should not expect them to be there).

Note that the above information applies to CHARACTER variables and arrays
only. It does not apply to external CHARACTER functions or to intrinsic
CHARACTER functions. That is, no second length argument is passed to `FOO'
in this case:

CHARACTER X
EXTERNAL X
CALL FOO(X)

Nor does `FOO' expect such an argument in this case:

SUBROUTINE FOO(X)
CHARACTER X
EXTERNAL X

Because of this implementation detail, if a program has a bug such that
there is disagreement as to whether an argument is a procedure, and the type
of the argument is CHARACTER, subtle symptoms might appear.

Functions (FUNCTION and RETURN)

g77 handles in a special way functions that return the following types:

   * CHARACTER
   * COMPLEX
   * REAL(KIND=1)

For CHARACTER, g77 implements a subroutine (a C function returning void)
with two arguments prepended: `__g77_result', which the caller passes as a
pointer to a char array expected to hold the return value, and
`__g77_length', which the caller passes as an ftnlen value specifying the
length of the return value as declared in the calling program. For
CHARACTER*(*), the called function uses `__g77_length' to determine the size
of the array that `__g77_result' points to; otherwise, it ignores that
argument.

For COMPLEX, when `-ff2c' is in force, g77 implements a subroutine with one
argument prepended: `__g77_result', which the caller passes as a pointer to
a variable of the type of the function. The called function writes the
return value into this variable instead of returning it as a function value.
When `-fno-f2c' is in force, g77 implements a COMPLEX function as gcc's
`__complex__ float' or `__complex__ double' function (or an emulation
thereof, when `-femulate-complex' is in effect), returning the result of the
function in the same way as gcc would.

For REAL(KIND=1), when `-ff2c' is in force, g77 implements a function that
actually returns REAL(KIND=2) (typically C's double type). When `-fno-f2c'
is in force, REAL(KIND=1) functions return float.

Names

Fortran permits each implementation to decide how to represent names as far
as how they're seen in other contexts, such as debuggers and when
interfacing to other languages, and especially as far as how casing is
handled.

External names--names of entities that are public, or "accessible", to all
modules in a program--normally have an underscore (`_') appended by g77, to
generate code that is compatible with f2c. External names include names of
Fortran things like common blocks, external procedures (subroutines and
functions, but not including statement functions, which are internal
procedures), and entry point names.

However, use of the `-fno-underscoring' option disables this kind of
transformation of external names (though inhibiting the transformation
certainly improves the chances of colliding with incompatible externals
written in other languages--but that might be intentional.

When `-funderscoring' is in force, any name (external or local) that already
has at least one underscore in it is implemented by g77 by appending two
underscores. (This second underscore can be disabled via the
`-fno-second-underscore' option.) External names are changed this way for
f2c compatibility. Local names are changed this way to avoid collisions with
external names that are different in the source code---f2c does the same
thing, but there's no compatibility issue there except for user expectations
while debugging.

For example:

Max_Cost = 0

Here, a user would, in the debugger, refer to this variable using the name
`max_cost__' (or `MAX_COST__' or `Max_Cost__', as described below). (We hope
to improve g77 in this regard in the future--don't write scripts depending
on this behavior! Also, consider experimenting with the `-fno-underscoring'
option to try ...
Zgłoś jeśli naruszono regulamin