jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) (10/22/90)
Hi - We have a library written in Fortran77 which includes a block data subroutine. If we use "ar" to archive the object files of the library, and then try to compile a program using the resulting "lib???.a" file, everything works fine EXCEPT the block data subroutine is never executed (that is, the initializations are not made). If the block data object file is linked in explicitly with the fortran compiler, then the initializations are done. Archiving the block data subroutine does work elsewhere (at least on computers running BSD4.3). It does not work on our SGI Personal Iris, (running IRIX version 3.2 I believe - but am not positive... I can find out if it makes a difference). Is this a problem with SGI's archiver, or archivers on machines running System V-like operating systems in general? We do not have a "ranlib" program on the SGI; the "ar" program creates the symbol tables that the loader needs (we can call normal subroutines that have been archived and it works fine). Thanks, Jeff -- /****************************************************************************** ** Jeff Biesiadecki ** University of Illinois, Urbana-Champaign ** ** jeffb@aquifer.las.uiuc.edu ** Departments of Geology and Computer Science ** ******************************************************************************/
burley@world.std.com (James C Burley) (10/22/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
Hi -
We have a library written in Fortran77 which includes a block data
subroutine. If we use "ar" to archive the object files of the library,
and then try to compile a program using the resulting "lib???.a" file,
everything works fine EXCEPT the block data subroutine is never executed
(that is, the initializations are not made). If the block data object file
is linked in explicitly with the fortran compiler, then the initializations
are done.
Hi back! I know nothing about "ar" or "lib???.a" files. But in Fortran,
there is a specification for forcing the inclusion of a BLOCK DATA program
unit in a program. It is EXTERNAL, believe it or not. For example:
PROGRAM FOO
EXTERNAL BDATA
COMMON /X/I
PRINT *,I
END
BLOCK DATA BDATA
COMMON /X/I
DATA I/5/
END
Without "EXTERNAL BDATA", the block data program unit must be explicitly
linked with the program, or whatever wording to that affect is appropriate
(since the standard doesn't really talk about linking). With it, the linker
should complain if it can't find a block data program unit named BDATA when
linking FOO, and thus should also pull it in from any library it is
searching.
Give this approach a try. I realize it requires you to modify the code
using the block data program unit, but that might be a good idea anyway, to
improve its portability. However, be aware that some nonconforming
implementations of Fortran might do the wrong thing, like assume BDATA must
be a subroutine or function but NOT a block data program unit, so try testing
this approach using, say, the example above (i.e. put BDATA in a library using
"ar" and link it to FOO after compiling both).
James Craig Burley, Software Craftsperson burley@world.std.com
silvert@cs.dal.ca (Bill Silvert) (10/22/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: >We have a library written in Fortran77 which includes a block data >subroutine. If we use "ar" to archive the object files of the library, >and then try to compile a program using the resulting "lib???.a" file, >everything works fine EXCEPT the block data subroutine is never executed >(that is, the initializations are not made). If the block data object file >is linked in explicitly with the fortran compiler, then the initializations >are done. This is a common (:)) problem which arises from the fact that the linker looks only for subroutines that are called, and since block data is not called, it doesn't get linked. One sure fix is to combine the block data unit with a subroutine in one file, since the entire file with both units will then get loaded if the subroutine is called. -- William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2. Tel. (902)426-1577 UUCP=..!{uunet|watmath}!dalcs!biomel!bill BITNET=bill%biomel%dalcs@dalac InterNet=bill%biomel@cs.dal.ca
ddh@hare.cdc.com (Dan Horsfall) (10/22/90)
In article <BURLEY.90Oct22050633@world.std.com> burley@world.std.com (James C Burley) writes: > In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: > > We have a library written in Fortran77 which includes a block data > subroutine. If we use "ar" to archive the object files of the library, > and then try to compile a program using the resulting "lib???.a" file, > everything works fine EXCEPT the block data subroutine is never executed > (that is, the initializations are not made). If the block data object file > is linked in explicitly with the fortran compiler, then the initializations > are done. > Keep in mind here a terminology issue: block data subprograms are not executable. They by definition contain no executable code. They cannot be "called". > Hi back! I know nothing about "ar" or "lib???.a" files. But in Fortran, > there is a specification for forcing the inclusion of a BLOCK DATA program > unit in a program. It is EXTERNAL, believe it or not. For example: > > PROGRAM FOO > EXTERNAL BDATA > COMMON /X/I > PRINT *,I > END > > BLOCK DATA BDATA > COMMON /X/I > DATA I/5/ > END > > Without "EXTERNAL BDATA", the block data program unit must be explicitly > linked with the program, or whatever wording to that affect is appropriate > (since the standard doesn't really talk about linking). With it, the linker > should complain if it can't find a block data program unit named BDATA when > linking FOO, and thus should also pull it in from any library it is > searching. > I beg to differ. EXTERNAL for linking in block data routines is a "fairly common" extension, but is NOT standard. Here's the problem at the loader level: Block data subprograms contain no executable code. Thus, they do not contain an entry point. A while back, some compiler writers figured out that if they added an entry point to a block data routine (which actually makes it executable, tho usually the supporting code is an instant _return). Now, having an entry point makes it resolvable by other routines that declare the same symbol as an external reference. How to do this in a manner that doesn't actually execute the code? Declare the symbol EXTERNAL in some other routine. Not all vendors support this mechanism, but this doesn't mean they are nonconforming. MIPS is one of these; mips makes the sgi box; James Burley's otherwise exemplary solution doesn't apply to you. What you gotta do is force load your block data routines the same way you force load your main program to start the loading process, e.g.: f77 -o xxx main.o bdata.o libx.a ( In our case here, we use f77 -o xxx *.o *.a, and make sure that the right *.o's are available. Kludge, but the only solution.) -- Horse + Control Data Corporation Dan Horsfall +1-612-482-4622 + 4201 Lexington Ave North Internet ddh@dash.udev.cdc.com + Arden Hills MN 55126 USA
doog@travis.ssd.csd.harris.com (Doug Scofield) (10/22/90)
)From article <>, by burley@world.std.com (James C Burley):
)) In article <> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
))
)) [ user wishes linker to pull block data from library ]
)
) [ suggests using the EXTERNAL keyword to cause an external reference, ]
) [ which would in theory include the block data subprogram ]
)
) ... However, be aware that some nonconforming
) implementations of Fortran might do the wrong thing ...
Actually, implementations may do whatever they want in this case.
Block data subprogram names are defined to be global to the
execution unit (16.1), and block data names are allowed in EXTERNAL
statements (8.7), but no functional use is described. In fact, this
is explicitly stated in (B16):
The name of a block data subprogram has no explicit use within
the FORTRAN language. It is available for documentation and
for possible use within a computer environment.
This "possible use" would include what you require. An innocuous
global definition of the block data name would be required in the
block data object, and a global reference would be generated within
the source object. Some vendors may be hesitant to do the latter,
as it requires generating a dummy reference for every unused
EXTERNAL name.
--
doug scofield doog@ssd.csd.harris.com (preferred)
harris computer systems uunet!hcx1!doog
system@alchemy.chem.utoronto.ca (System Admin (Mike Peterson)) (10/23/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: >We have a library written in Fortran77 which includes a block data >subroutine. If we use "ar" to archive the object files of the library, >and then try to compile a program using the resulting "lib???.a" file, >everything works fine EXCEPT the block data subroutine is never executed >(that is, the initializations are not made). ... You can make this work properly on most normal systems (Sun, DEC/Ultrix, Cray/UNICOS, IBM RS/6000, SGI) by: - giving the BLOCK DATA routine a unique name. - putting an 'EXTERNAL blockdataname' statement in the subroutine(s) that want the COMMON block to be loaded. Note that this technique will NOT work reliably on Apollo systems :-(. -- Mike Peterson, System Administrator, U/Toronto Department of Chemistry E-mail: system@alchemy.chem.utoronto.ca Tel: (416) 978-7094 Fax: (416) 978-8775
vjs@rhyolite.wpd.sgi.com (Vernon Schryver) (10/23/90)
In article <27320@shamash.cdc.com>, ddh@hare.cdc.com (Dan Horsfall) writes: > ... mips makes the sgi box ... > Horse > + Control Data Corporation > Dan Horsfall +1-612-482-4622 + 4201 Lexington Ave North > Internet ddh@dash.udev.cdc.com + Arden Hills MN 55126 USA The preceding was probably a typo, but ... MIPS does not make IRIS's. Silicon Graphics Computer Systems, Inc. makes IRIS's. MIPS makes their own boxes. I'm not even sure which of the several silicon foundaries SGI is using for the MIPS R3000 that is probably in whichever SGI box is being mentioned. I don't think MIPS is in the silicon business any more. I think it's been years since any IRIS contained any hardware manufactured by MIPS. It is or at least has been true that packing cases leave Mtn.View loading docks with labels that do not mention SGI but do say "Cyber". It is true SGI ships modified versions of MIPS compilers for some but not all languages. MIPS &co. are great guys with good machines and all that, but everyone working at SGI knows they are not as great as SGI. Vernon Schryver, vjs@sgi.com
milind@agni.cc.nd.edu (Milind Saraph) (10/23/90)
|> |>Hi - |> |>(stuff deleted) |> |>Archiving the block data subroutine does work elsewhere (at least on computers |>running BSD4.3). It does not work on our SGI Personal Iris, (running |>IRIX version 3.2 I believe - but am not positive... I can find out if it |>makes a difference). |> |>Is this a problem with SGI's archiver, or archivers on machines running |>System V-like operating systems in general? We do not have a "ranlib" |>program on the SGI; the "ar" program creates the symbol tables that the |>loader needs (we can call normal subroutines that have been archived and |>it works fine). |> |>Thanks, |>Jeff |> |>-- |>/********************************************************************* ********** |>** Jeff Biesiadecki ** University of Illinois, Urbana-Champaign ** |>** jeffb@aquifer.las.uiuc.edu ** Departments of Geology and Computer Science ** |>********************************************************************** *********/ This has certainly been a problem on Stellar and Ardent machines (SYS-V like OS). -- milind
dik@cwi.nl (Dik T. Winter) (10/23/90)
In article <1990Oct22.130143.29775@cs.dal.ca> bill%biomel@cs.dal.ca writes: > One sure fix is to combine the block > data unit with a subroutine in one file, since the entire file with > both units will then get loaded if the subroutine is called. Probably sure within this context (Unix systems). Certainly not sure in general. I know of at least one (non Unix) system where this will fail. In short: there is no solution that will work everywhere, except explicitly loading the block data subprogram. -- dik t. winter, cwi, amsterdam, nederland dik@cwi.nl
burley@world.std.com (James C Burley) (10/23/90)
In article <27320@shamash.cdc.com> ddh@hare.cdc.com (Dan Horsfall) writes: In article <BURLEY.90Oct22050633@world.std.com> burley@world.std.com (James C Burley) writes: > [...] in Fortran, > there is a specification for forcing the inclusion of a BLOCK DATA program > unit in a program. It is EXTERNAL, believe it or not. For example: > > PROGRAM FOO > EXTERNAL BDATA > COMMON /X/I > PRINT *,I > END > > BLOCK DATA BDATA > COMMON /X/I > DATA I/5/ > END > > Without "EXTERNAL BDATA", the block data program unit must be explicitly > linked with the program, or whatever wording to that affect is appropriate > (since the standard doesn't really talk about linking). With it, the linker > should complain if it can't find a block data program unit named BDATA when > linking FOO, and thus should also pull it in from any library it is > searching. > I beg to differ. EXTERNAL for linking in block data routines is a "fairly common" extension, but is NOT standard. [...] I beg to differ right back, with a clarification of what I said above: use of EXTERNAL for specifying a BLOCK DATA program unit name IS standard. How this affects program linking is NOT standard, because (as I said above) the standard doesn't really talk about linking. I believe if you look into the history of the F77 standard, you'll find that the reason Page 8-9 lines 30 and 31 allow block data subprogram names in the EXTERNAL statement was to accommodate systems allowing linking of libraries that needed a means to allow procedures in a library to specify that they also needed a corresponding BLOCK DATA program unit from that same library. (Another posting suggests that if one procedure is needed from a compiled file, all procedures and BLOCK DATA subprograms will be retrieved from the library originally specified by that file; that statement is incorrect, since in Fortran each program unit is independent from each other and many systems take advantage of that fact by treating them separately. And certainly the standard doesn't specify any concept referred to as a "source file" containing more than one program unit.) It stands to reason, therefore, that anyone designing a new Fortran system and wishing to be standard-conforming would support both the letter and the spirit of the standard. Since the 77 standard could not possibly specify how programs were to be put together from program units in terms of "linking", "loading", or whatever, without many problems, it also could not explicitly say that "EXTERNAL BDATA" means "make sure BLOCK DATA BDATA subprogram is in the program image along with its initializations". But any responsible developer would interpret it that way when providing the facility for placing Fortran subprograms in libraries. (Of course, "responsible" here is a subjective term!) So, if Apollo, for example, doesn't do this, it can be said their systems do not effectively implement the 77 standard across their "range" of their system, unless they disavow the use of their library packaging for Fortran. Further, if specifying "BLOCK DATA BDATA" is not permitted, either resulting in a compile-time message or a link-time message that there is no such subroutine or function named BDATA when, in fact, there is a BLOCK DATA program unit present named BDATA, then their system does not conform to even the letter of the ANSI FORTRAN 77 standard. All readers should note that the Fortran standards, both 77 AND 90, DISALLOW initialization (via DATA or, for 90, via initial values specified on type- declaration statements) of entities in common blocks except within BLOCK DATA subprograms, and there only for named common blocks (i.e. you can't provide initial values for entities in blank common). In other words, the following very effective solution is, unfortunately, nonstandard, even though I believe it will work on every single machine that supports Fortran to any reasonable extent (i.e. here's a recommendation, though it isn't standard): PROGRAM MINE !Or subroutine or function. INTEGER NOTHING COMMON /NOTHING/ NOTHING ...other specification statements... IF (NOTHING.EQ.12345) GOTO 99999 !Never happens. ...regular executable stuff... STOP !Or RETURN, as appropriate. 99999 CALL DOES_NOTHING !Nobody goes here. END SUBROUTINE DOES_NOTHING !Instead of BLOCK DATA DOES_NOTHING. INTEGER NOTHING COMMON /NOTHING/ NOTHING ...other stuff you want to put in a BLOCK DATA... DATA NOTHING/0/ !Make sure it isn't 12345. ...other DATA statements you'd put in a BLOCK DATA... END For every distinct BLOCK DATA subprogram you want, make a procedure out of it instead, giving it, of course, a unique name, and give it a special common area all its own with its own unique name, along with a unique variable. Then initialize that variable to zero via a DATA statement. Include no executable code in the procedure. Then the main program (or procedure that wants the BLOCK DATA included, if you can find one that doesn't need to be super-optimal) tests each of the special variables for common areas and jumps to statements that call the procedures that represent the BLOCK DATAs. The CALLs never happen because the variables are never equal to the values tested. By doing this, you prevent almost any optimizing compiler (except a truly global optimizing compiler) from deciding that the calls will never happen and thus not emitting requests to the linker to include the corresponding procedures. (And, for a global optimizing compiler, it'd have to reference the procedures anyway, and thus include the initializations they perform, which is all you want.) If you're sure your Fortran implementation either doesn't do such nifty optimization, or that at least it still emits a request to link a procedure whose only reference(s) in a program unit have effectively been eliminated due to dead code removal, then you can drop the "IF...GO TO" statements that reach the useless CALLs. For a main program, this makes little difference, but for a library of often-used procedures, it can allow the procedures to still run at the speed at which they would have had your Fortran implementation obeyed the letter and the spirit of the standard. Again, the above solution is NONSTANDARD because a procedure (subroutine or function) cannot use DATA to specify initial values for variables in common blocks -- that is what BLOCK DATA is for, and that is why any implementation that does not fully implement "EXTERNAL BDATA" meaning "make sure you've got a [subroutine, function, or] block data subprogram linked in with the program" is, in my opinion, not standard-conforming. However, the above solution will work on any system I can imagine, as long as it accepts the nearly ubiquitous extension allowing DATA for variables in common from within subroutines or functions. If your system does not allow that, I bet it doesn't allow Fortran libraries in the first place, or that it does EXTERNAL correctly! (Or the developers were truly obnoxious/ignorant/ underpaid :-). James Craig Burley, Software Craftsperson burley@world.std.com
sjc@key.COM (Steve Correll) (10/26/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu>, jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: > We have a library written in Fortran77 which includes a block data > subroutine. If we use "ar" to archive the object files of the library, > and then try to compile a program using the resulting "lib???.a" file, > everything works fine EXCEPT the block data subroutine is never executed >... > Is this a problem with SGI's archiver, or archivers on machines running > System V-like operating systems in general? Yes, most Unix System V Release 3 linkers behave differently than most BSD4.3 linkers, in a fashion that is sufficient to explain your problem. Suppose there is a .o file in the archive library which does not define any symbol which the linker has seen previously, except for one: an uninitialized common block. Should the linker bind that .o file into the program on the basis of that common block alone, even though the .o file does not affect the meaning of that common block? Most BSD linkers answer "yes" and most SVR3 linkers answer "no". The answer _can_ affect the meaning of the program. To sidestep arguments about the Fortran standard for the moment, consider (sorry) a C example: file main.c: int c; /* Think of this as uninitialized common */ main() { return com1(); } file com1.c: int c; /* Think of this as uninitialized common */ int d = 5; /* Think of this as initialized common */ com1() { return c + d; } file com2.c: int c = 6; /* Think of this as initialized common within blockdata */ Now do the following in /bin/sh: cc -c main.c cc -c com1.c cc -c com2.c ar cr lx.a com1.o com2.o cc -o main main.o lx.a ./main echo $? Most BSD systems will print "11" and most SVR3 systems will print "5" (because uninitialized common is 0 on Unix systems). If you say: nm main on most BSD systems, both "c" and "d" will have storage class "DATA", indicating that they have been initialized because com2.o was bound. On most SVR3 systems, "c" will have storage class "BSS", indicating that it is uninitialized because com2.o was not bound. Now as for arguments about the Fortran 77 standard: James Craig Burley writes: > ...I believe if you look into > the history of the F77 standard, you'll find that the reason Page 8-9 lines 30 > and 31 allow block data subprogram names in the EXTERNAL statement was to > accommodate systems allowing linking of libraries that needed a means to > allow procedures in a library to specify that they also needed a corresponding > BLOCK DATA program unit from that same library. > ...It stands to reason, therefore, that anyone designing a new Fortran system > and wishing to be standard-conforming would support both the letter and the > spirit of the standard...any responsible developer would interpret it that > way... I am acquainted with language-independent compiler optimizers which delete unreferenced global imports, causing EXTERNAL BDATA to vanish without a trace. Perhaps you are not accustomed to such aggressive optimization. Clearly it's a matter of taste, but around here we tend to regard complaints about such deletions with the same sympathy we extend to complaints about our not allocating unSAVEd local variables in memory: if the standard doesn't say you can rely on it, please don't. Consider that the Fortran 77 standard says (2.12) that when a procedure _reference_ is _executed_, the procedure must be "available" (the Fortran 77 circumlocution to avoid talking about "linking"). Can anyone find a provision in the standard which says that the appearance of a procedure name in an EXTERNAL statement requires the procedure to be "available"? I can't. In its absence, I can imagine a perverse user arguing that the following program is standard-conforming even if X is not available: EXTERNAL X END and complaining that a processor which refuses to construct an executable program in the absence of X fails to conform to Fortran 77! -- sjc@key.com or ...{sun,pyramid}!pacbell!key!sjc Steve Correll
burley@world.std.com (James C Burley) (10/26/90)
In article <2208@key.COM> sjc@key.COM (Steve Correll) writes: James Craig Burley writes: > ...I believe if you look into > the history of the F77 standard, you'll find that the reason Page 8-9 lines 30 > and 31 allow block data subprogram names in the EXTERNAL statement was to > accommodate systems allowing linking of libraries that needed a means to > allow procedures in a library to specify that they also needed a corresponding > BLOCK DATA program unit from that same library. > ...It stands to reason, therefore, that anyone designing a new Fortran system > and wishing to be standard-conforming would support both the letter and the > spirit of the standard...any responsible developer would interpret it that > way... I am acquainted with language-independent compiler optimizers which delete unreferenced global imports, causing EXTERNAL BDATA to vanish without a trace. Perhaps you are not accustomed to such aggressive optimization. Clearly it's a matter of taste, but around here we tend to regard complaints about such deletions with the same sympathy we extend to complaints about our not allocating unSAVEd local variables in memory: if the standard doesn't say you can rely on it, please don't. Consider that the Fortran 77 standard says (2.12) that when a procedure _reference_ is _executed_, the procedure must be "available" (the Fortran 77 circumlocution to avoid talking about "linking"). Can anyone find a provision in the standard which says that the appearance of a procedure name in an EXTERNAL statement requires the procedure to be "available"? I can't. In its absence, I can imagine a perverse user arguing that the following program is standard-conforming even if X is not available: EXTERNAL X END and complaining that a processor which refuses to construct an executable program in the absence of X fails to conform to Fortran 77! -- sjc@key.com or ...{sun,pyramid}!pacbell!key!sjc Steve Correll I am accustomed to extremely aggressive optimization, both that which has been implemented and that which I've only thought about. The program you show above, "EXTERNAL X;END", is indeed standard-conforming even if X is not available, because X is not necessarily a procedure: in fact it appears the standard requires that it must be a BLOCK DATA subprogram. (Because in the main program unit, it is not referenced as a subroutine or function, and a BLOCK DATA subprogram is the only alternative.) Unfortunately, the standard does not appear to specify the effect of specifying a BLOCK DATA subprogram name in an EXTERNAL statement. So it appears that your mythical user complaining about a processor refusing to construct an executable program in the absence of X indeed has a point: it is a valid program, and X need not be present, even though I would argue a reasonable implementation should complain that there is no BLOCK DATA X (via an error message from, perhaps, a multi-language linker requiring the user to look up the message in the Fortran book to yield the explanation that perhaps a BLOCK DATA X is missing). However, as I pointed out in my original posting, the only reasonably way for an implementation to deal with "EXTERNAL FOO" where FOO is not referenced anywhere else in the same program unit is for it to assume FOO is a BLOCK DATA program unit and to ensure that, if it indeed turns out that FOO is found to be a BLOCK DATA program unit, its initial values for variables in COMMON are used for the program. If FOO turns out to be a subroutine or function, an implementation is free to ignore it, if it is capable of doing that while still dealing with the possible BLOCK DATA FOO case instead. Now, you can play language lawyer games -- like the company that said their implementation was standard-conforming even though the STOP statement did not in fact stop the program, because the standard didn't actually specify what happens the moment after the program is "stopped" -- and say that an implementation is standard-conforming that totally ignores EXTERNAL FOO where FOO is otherwise unreferenced in the program unit. However, if you are taking things this literally from a standards perspective, then please note that there is NO STANDARD WAY to initialize variables in common! According to the standard, that can ONLY be done via BLOCK DATA. And a system that provides some mechanism whereby BLOCK DATA can be ignored (the "library problem" that started all this), and yet refuses to honor a clear accommodation in the standard to deal with the problem, fails to honor the spirit of the standard, just as does one that, when running a program saying "PRINT *,2.0*3.0", outputs "2.0" because the standard doesn't actually specify precision requirements. After all, if subroutines and functions need only be "available" when they are actually "referenced" at run time, then (unless there's some wording to override this assumption in the standard that I can't remember seeing offhand), the same goes for BLOCK DATA in a system that implements everything using libraries. Yet there is NO WAY to "reference" a BLOCK DATA subprogram except via the "EXTERNAL FOO" construct. (And note that your reference to complaints about unSAVEd variables not being SAVEd is, in my opinion, an invalid comparison in this context. The spirit of the standard regarding BLOCK DATA is as I state above; whereas the standard clearly states that you can't depend on the value of an unSAVEd variable between procedure invocations. People complaining about a system not honoring the EXTERNAL FOO convention for ensuring the linking-in of a BLOCK DATA FOO residing in a library have a very legitimate gripe, language-lawyer games notwithstanding. People who complain about unSAVEd variables not retaining their values between procedure invocations are just plain wrong; but note that many implementations nevertheless provide command- line qualifiers to effectively force the SAVEing of all appropriate variables, so given that so many implementations bend over backwards to accommodate incorrect or very old code, why not deal with the relatively trivial case of EXTERNAL FOO possibly referring to a necessary BLOCK DATA FOO?) James Craig Burley, Software Craftsperson burley@world.std.com
jerry@violet.berkeley.edu (Jerry Berkman) (11/22/90)
In article <BURLEY.90Oct23041048@world.std.com> burley@world.std.com (James C Burley) writes:
...
==All readers should note that the Fortran standards, both 77 AND 90, DISALLOW
==initialization (via DATA or, for 90, via initial values specified on type-
==declaration statements) of entities in common blocks except within BLOCK
==DATA subprograms, and there only for named common blocks (i.e. you can't
==provide initial values for entities in blank common). In other words, the
==following very effective solution is, unfortunately, nonstandard, even though
==I believe it will work on every single machine that supports Fortran to any
==reasonable extent (i.e. here's a recommendation, though it isn't standard):
== SUBROUTINE DOES_NOTHING !Instead of BLOCK DATA DOES_NOTHING.
== INTEGER NOTHING
== COMMON /NOTHING/ NOTHING
== ...other stuff you want to put in a BLOCK DATA...
== DATA NOTHING/0/ !Make sure it isn't 12345.
== ...other DATA statements you'd put in a BLOCK DATA...
== END
==... the above solution will work on any system I can imagine, as long as
==it accepts the nearly ubiquitous extension allowing DATA for variables in
==common from within subroutines or functions.
==James Craig Burley, Software Craftsperson burley@world.std.com
This is flagged as an error by VS FORTRAN which is IBM's mainframe FORTRAN
compiler. Also by WATFOR77 on our IBM mainframe.
There is probably no easy way which works on all systems to get block data's
to load. Some UNIX systems will load a block data in a library if it is in
the same source file as another program segment being loaded, some UNIX systems
will not. All the non-UNIX systems I have used would not.
- Jerry Berkman, U.C. Berkeley, jerry@violet.berkeley.edu
3003jalp@ucsbuxa.ucsb.edu (Applied Magnetics) (11/27/90)
In article <1990Nov22.074157.15813@agate.berkeley.edu> jerry@violet.berkeley.edu (Jerry Berkman) writes: >... >There is probably no easy way which works on all systems to get block data's >to load. Some UNIX systems will load a block data in a library if it is in >the same source file as another program segment being loaded, some UNIX systems >will not. All the non-UNIX systems I have used would not. > - Jerry Berkman, U.C. Berkeley, jerry@violet.berkeley.edu Our IBM mainframe with VS Fortran will do it. The loader granularity for libraries (TXTLIB's) is at the object file level (TEXT). If an archived object file contains a subprogram you need and a block data, both get loaded. (This is with VM/XA and CMS). I agree that there is no universal solution. Just for the heck of it, here is yet another way to violate the standard: C <Never call this routine! Just leave it near your main. SUBROUTINE KABOOM CALL BD END C <This BD is no subroutine. It's the block data. Tee hee. C <Hope this will fool the loader. Anybody out there have a loader that refuses to cooperate? --Pierre Asselin, R&D, Applied Magnetics Corp.
shank@buphy.BU.EDU (Jim Shank) (11/27/90)
In article <1990Nov22.074157.15813@agate.berkeley.edu> jerry@violet.berkeley.edu (Jerry Berkman) writes: >>... >>There is probably no easy way which works on all systems to get block data's >>to load. Some UNIX systems will load a block data in a library if it is in >>the same source file as another program segment being loaded, some UNIX systems >>will not. All the non-UNIX systems I have used would not. >> - Jerry Berkman, U.C. Berkeley, jerry@violet.berkeley.edu >I agree that there is no universal solution. Just for the heck of it, >here is yet another way to violate the standard: >C <Never call this routine! Just leave it near your main. > SUBROUTINE KABOOM > CALL BD > END >C <This BD is no subroutine. It's the block data. Tee hee. >C <Hope this will fool the loader. I always thought the way to do this was to declare the Block Data subprogram EXTERNAL in the main routine: PROGRAM MAIN EXTERNAL BLKDAT . . . STOP This forces the linker to include the Block data subprogram.
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (11/27/90)
In article <7388@hub.ucsb.edu>, 3003jalp@ucsbuxa.ucsb.edu (Applied Magnetics) writes: > C <Never call this routine! Just leave it near your main. > SUBROUTINE KABOOM > CALL BD > END > C <This BD is no subroutine. It's the block data. Tee hee. > C <Hope this will fool the loader. > > Anybody out there have a loader that refuses to cooperate? I know that the Burroughs compilers used different names for COMMON blocks (e.g. "/ABLOCK/") and subroutines (e.g. "ABLOCK"). That caught quite a lot of mistakes. I imagine that a Fortran compiler could do the same for block data, e.g. "*BD*". That would give you trouble. It's a compiler choice, not a loader one. -- I am not now and never have been a member of Mensa. -- Ariadne.
burley@pogo.ai.mit.edu (Craig Burley) (11/27/90)
In article <69366@bu.edu.bu.edu> shank@buphy.BU.EDU (Jim Shank) writes:
I always thought the way to do this was to declare the Block Data
subprogram EXTERNAL in the main routine:
PROGRAM MAIN
EXTERNAL BLKDAT
.
.
.
STOP
This forces the linker to include the Block data subprogram.
Not according to the standard, but yes, I agree this is the most
standard-conforming way to deal with things, both from the user's and
the implementor's point of view.
The problem is that systems that "extend" Fortran by providing certain
weird nonstandard things like source files that contain multiple program
units and, in this case, libraries from which only program units referenced
by the program currently being linked/loaded are actually loaded, fail to
take into account and thus implement in an obvious and standard-acceptable
way certain Fortran facilities like BLOCK DATA. (Yes, I know these are very
common things, but their behaviors aren't even discussed in the standard.)
As I've pointed out before, the ONLY standard way to pre-initialize (DATA)
variables in common areas is to: use named commons; and initialize them via
DATA in BLOCK DATA program units. A system that provides libraries and yet
does not implement in the expected way the standard extension (that by the
way in the standard has NO explanation I can find) you showed in the above
example by ensuring that any BLOCK DATA FOO in a library is loaded/linked if
at least one other program unit that is loaded/linked contains an EXTERNAL
FOO statement is, in my opinion, not a complete implementation of Fortran.
It may be an ANSI-conforming implementation, but that's a different question.
For example, an implementation may be ANSI-conforming as long as all your
program units are in a single source file, but not if you put them in
separate source files even though that implementation handles multiple sources
(and thus objects) in a load/link command for other languages. Even though
it appears to handle Fortran this way also, and works in many cases, the
fact that, say, linkage involving user-defined procedures having the same
names as intrinsics does not work still wouldn't prevent the implementation
from being ANSI-conforming as long as the problem didn't exist in SOME
method of writing Fortran code (in my example, one big source file with all
the program units, hence one big object module).
So a system that had such a problem could be ANSI-conforming but, in my
opinion, would not be complete Fortran in terms of the natural combination
of its capabilities (multiple source files + ANSI Fortran support should =
ANSI Fortran support using multiple source files).
That is why I assert that systems failing to load/link BLOCK DATA FOO from
a library when at least one load/linked program unit says EXTERNAL FOO are
not complete Fortran, because they a) have libraries, b) may conform to ANSI
FORTRAN 77, but c) do not conform to ANSI FORTRAN 77 in the natural way when
libraries are used in certain standard ways.
Such systems require the programmer either to use nonstandard constructs within
their programs (which in itself should be a clear argument that these systems
are not complete Fortran) or use extraordinary facilities like special
specifications when loading/linking or generating the library (which is
redundant since there's an ANSI feature provided that should be usable; and
if the programmer does not know this and uses the extraordinary facilities, he
or she might well be producing nonportable code without knowing it).
Note that this does not mean I necessarily have a beef with a Fortran system
implementation (or implementor) that fails to deal with this feature, IF the
implementor has no control over the loader/linker (i.e. it comes from another
vendor and is highly inflexible or primitive).
However, I DO have a beef with people who say "we can't have EXTERNAL FOO force
FOO to be loaded/linked since it might not be a BLOCK DATA (and we can't tell
the difference when we need to) and we don't want to put anything in the
executable image that is not actually referenced except possibly via EXTERNAL".
This is WRONG. They certainly CAN force FOO to be loaded/linked, because a)
I doubt many programs ever use EXTERNAL without actually referencing the name,
and b) assuming they provide some nonstandard or nonportable means to solve the
BLOCK DATA problem, they should instead solve it according to the standard
and relegate designations like "I know I said EXTERNAL FOO, perhaps, but I
don't really need it if I don't actually reference it" to the realm of
nonstandard and nonportable behavior.
I hold this position simply because failing to optimally omit an EXTERNALed
procedure from a loaded/linked program that doesn't actually reference it has
no effect on the correctness of a program, and hence can be relegated to the
category of problems solved via nonstandard and nonportable means. On the
other hand, failing to load/link an EXTERNALed BLOCK DATA in a loaded/linked
program definitely CAN and most often WILL affect the correctness of the
program. Anyone holding the opposite position in light of these facts
(assuming these are facts, i.e. I'm not simply mistaken about something)
should, in my opinion, not be writing compilers, linkers, operating systems,
and so on -- anything that has a "standard" of sorts for it. Nor should they
be selling or manufacturing such products. They don't have the temperment
for it -- they'd do better at end-user applications, where saving a bit of
space or time at the expense of full generality might be ok as long as they
know when they don't need full generality. Myself, I think I have not yet
developed the temperment for end-user programming: i.e. this is not a
criticism of one's person, but of whether they're in the right field of
labor within the software industry. There's plenty of room for all of us!
James Craig Burley, Software Craftsperson burley@ai.mit.edu
3003jalp@ucsbuxa.ucsb.edu (Applied Magnetics) (11/28/90)
The following is from Harbison and Steele, "C a Reference Manual", 1st ed. section 4.8. Emphasis mine. ...It is a well-known deficiency in C that defining and referencing occurrences of external declarations are difficult to distinguish. In general, compilers use one of three complicated schemes to determine when a top level declaration is a defining occurrence. ... 4.8.2 The FORTRAN "named COMMON" Solution This scheme is so named because it is related to the way multiple references to a FORTRAN COMMON block are merged into a single defining occurrence in some FORTRAN implementations. ...At link time, all external declarations for the same identifier (in all C object files) are combined and a single defining occurrence is conjured, NOT NECESSARILY ASSOCIATED WITH ANY PARTICULAR FILE. If any declaration specified an initializer, that initializer is used to initialize the data object. (If several declarations did, the results are unpredictable.) This solution is the most painless for the programmer, the most demanding on system software and the most likely to lead to confusion on the part of people reading a program. It is hypothesized that the presence of a linker on the PDP-11 that handled these COMMON declarations lured early C implementors into depending on this capability End of quote. THAT's the problem. We're all stuck with loaders that recognize 1) REFERENCED external symbols, which must be resolved by loading additional defining modules, 2) DEFINED external symbols, which must not conflict among themselves and are loaded to resolve the former kind, and finally 3) COMMON external symbols, which are collected during the loading phase and finally fused together without loading anything else. I assume that the COMMON symbol semantics originated at IBM. The ANSI F.77 standard itself explicitly declines to address those issues (sect. 1.3.2). Your implementation can do what it wants to you. In the future, I think that I will keep my block datas in SOURCE form and require the programmer to INCLUDE a copy exactly once in his source file. The INCLUDE statement was discussed eralier in this group. It's not ANSI, but it's MIL-something. Almost all compilers have some form of it. They're all different, of course, but the functionality is there, so you can port. --Pierre Asselin, R&D, Applied magnetics Corp. I speak for me.