Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!sun-barr!decwrl!world!burley From: burley@world.std.com (James C Burley) Newsgroups: comp.lang.fortran Subject: Re: archiving block data subroutines... Message-ID: Date: 23 Oct 90 11:10:48 GMT References: <1990Oct22.033107.5159@ux1.cso.uiuc.edu> <27320@shamash.cdc.com> Sender: burley@world.std.com (James C Burley) Followup-To: comp.lang.fortran Organization: The World Lines: 136 In-Reply-To: ddh@hare.cdc.com's message of 22 Oct 90 14:42:22 GMT In article <27320@shamash.cdc.com> ddh@hare.cdc.com (Dan Horsfall) writes: In article 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