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.