[comp.lang.fortran] Locating unDIMENSIONed arrays in large Fortran Codes

HDK@PSUVM.BITNET (H. D. Knoble) (04/22/88)

The problem solved here is finding WHERE a so-called "unresolved external
reference" (or in case of CMS LOAD: "The following names are undefined")
is located. You need to know WHERE when the "unresolved xref" is really
an unDIMENSIONed array, which because it is undimensioned is compiled as
a FUNCTION call. When you have a rather large Fortran code, this can be
difficult to find. This memo addresses this case.

CASE I - CMS:

From CMS, first make a large (at least 10000 Block) TDISK, and access
this as your A-disk. E.G. REL A#TDISK 2FF A 10000#ACC 100 B/B  will
access a (TEMP)-disk as your A-disk and your 100 Disk (normally A-disk)
as R/O B-disk.  Then issue:

FILEDEF DISK SYSLIB VSF2LINK TXTLIB *
LKED fn (XREF DISK NOTERM

This will put two files on your A-disk: fn LKEDIT, and fn LOADLIB; a
temporary scratch file is also written to your A-disk. You can erase
fn LOADLIB as all you are interested in is fn LKEDIT.


CASE II - MVS:

First create the job, realizing full well that GO (called DATA in
PSU Cataloged Procedures) step won't run because there are unresolved
external references (which you know from the CMS LOAD command display).
The following JCL may be used to do this:

//V03XXXXX JOB
//* Assume your CMS VS Fortran object code is in fn TEXT fm.
//* To build the JOB, issue the following CMS command:
//*               COPYFILE  fn TEXT fm XREF JOB E (APPEND
//* Then to run it issue: RUNMVS XREF JOB
//*
// EXEC FVLG,PARM.OBJECT='XREF',LIB1=EMPTYPDS
//*
//* LIB1=EMPTYPDS cancels action of having PSU's Fortran library
//* inadvertently resolving things like LOC, FXY, etc. You can also
//* append the string, LIB2=EMPTYPDS to cancel resolution via IMSL.
//*
/*OUTPUT NODE DEST=nodeid.userid
//OBJECT.SYSLMOD DD UNIT=SYSDA,SPACE=(CYL,(50,100,1),RLSE)
//OBJECT.SYSPRINT  DD SYSOUT=(N,,NODE)
//OBJECT.INPUT DD *

First RUNMVS the above job, and use RDRLIST and RECEIVE its output as
fn LKEDIT A.


BOTH MVS and CMS:

Note that the Linkeditor output is now called fn LKEDIT A. You can use
the BREAKUP command to enable you to Xedit this file if it is large;
note that this file may be VERY large (e.g one case involving 400 Fortran
subprograms was larger than 60000 lines).  After fn LKEDIT A is broken
up into editable files, you can either Xedit each and search them or use
the GLOCATE command to search for the strings described in the next two
paragraphs.

The Linkeditor output will enable you to find out which of your
subprograms are calling unresolved external references, in this case
refering to an undimensioned array that appears syntactically to be an
Xref.  The Linkeditor MVS PARM.OBJECT='XREF' or CMS option (XREF produces
a Map AND Cross Reference list of all external references.  You should
also see in the very beginning Linkeditor output the same unresolved
xrefs that the CMS LOAD command reported.  At the very end of the
Linkeditor output, you will see the message: IEW0132 ERROR - SYMBOL
PRINTED IS AN UNRESOLVED EXTERNAL REFERENCE.  (It should have read ...
TRULY UNRESOLVED ..., as there are unresolved Fortran Library routines
which will be picked up during load - by "program Fetch, the system
routine that loads the loadMODULE into memory and initiates execution.

Now, look for the string "$UNRESOLVED  " in the output (i.e.  use the
Xedit subcommand: ALL /$UNRESOLVED  "/ and note presence of the
trailing blanks because some legitimate dynamically loadable VS
Fortran Library routines will be flagged with the string
"$UNRESOLVED(W)"; the W means Warning and is not an error like the
Linkeditor message IEW0132, but rather a "soft" xref that will be
resolved by the runtime Library.

Suppose you have the unresolved external reference message (perhaps first
from the CMS LOADer, i.e. DMSLIO201W THE FOLLOWING NAMES ARE UNDEFINED:)
telling you Z (e.g.) is an unresolved external reference; and
you know this is an undimensioned array somewhere.  Once you find Z (for
example) in the (second table of the)  XREF output, i.e. hexaddress
Z $UNRESOLVED, note this hex address, then scroll backward to the MAP
portion (first table of the Linkeditor output).  The MAP lists each
subroutine with its starting addresses; "hexaddress" above will be an
address BETWEEN (i.e.  .GE.  and .LT.) two of the subroutine starting
addresses; the subprogram whose name is associated with one of these two
bracketing addresses (of course) "contains" the unresolved external
reference (in this case to Z).  This is, the subroutine that issues the
"call" (compiled as a function reference) in this example to Z(...) . Now
repeat this process for each unresolved xref, and you will have a list of
subprograms that you will need to Xedit ( and copy (or insert) the
missing DIMENSION (or declare with dimension) statements into.