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 ...
alvin888