Lost BLOCKDATA initialisation in LIB files 
Author Message
 Lost BLOCKDATA initialisation in LIB files

Can anyone explain why a BLOCKDATA unit in a LIB file may need to be prodded
into life with an EXTERNAL statement? I can see no reason why this should
ever be necessary.


Fri, 29 Aug 2008 02:14:49 GMT  
 Lost BLOCKDATA initialisation in LIB files


Quote:
> Can anyone explain why a BLOCKDATA unit in a LIB file may need to be
> prodded
> into life with an EXTERNAL statement? I can see no reason why this should
> ever be necessary.

Because it doesn't get explicitly referenced by the program using the
library (since block data procedures are never invoked). Adding the external
statement causes such a reference.

Regards,

Mike Metcalf



Fri, 29 Aug 2008 02:19:05 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:
> > Can anyone explain why a BLOCKDATA unit in a LIB file may need to be
> > prodded
> > into life with an EXTERNAL statement? I can see no reason why this
should
> > ever be necessary.

> Because it doesn't get explicitly referenced by the program using the
> library (since block data procedures are never invoked). Adding the
external
> statement causes such a reference.

> Regards,

> Mike Metcalf

Tnanks for this Mike

On the assumption that the BLOCKDATA initialisations are done at link-time,
a linker should be smart enough to check the LIB file for BLOCKDATA without
prompting with an EXTERNAL call. The only real use I can see in not
automatically linking BLOCK data from a LIB file is that you can initialise
COMMON from the host application with a separate BLOCKDATA; but this does
not seem particularly "safe" programming to me.

I guess the real answer is "fortran 77 - know the rules and use with
caution".



Sat, 30 Aug 2008 19:23:02 GMT  
 Lost BLOCKDATA initialisation in LIB files
Hello,

<snip>

Quote:
> On the assumption that the BLOCKDATA initialisations are done at link-time,
> a linker should be smart enough to check the LIB file for BLOCKDATA without
> prompting with an EXTERNAL call.

What if there are two versions of the program using two different
block data subprograms to initialize the same common blocks
stored within the same library?  How is the applications programmer
going to specify which to choose?

I've heard all sorts of reasons from compiler writers
about why block data subprograms should not be loaded
from libraries.  Apparently, that's why the standard
had to specify that an external in the program subprogram
was sufficient.

--
Cheers!

Dan Nagle
Purple Sage Computing Solutions, Inc.



Sat, 30 Aug 2008 19:41:29 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:
>>> Can anyone explain why a BLOCKDATA unit in a LIB file may need to be
>>> prodded
>>> into life with an EXTERNAL statement? I can see no reason why this
> should
>>> ever be necessary.

>> Because it doesn't get explicitly referenced by the program using the
>> library (since block data procedures are never invoked). Adding the
> external
>> statement causes such a reference.

>> Regards,

>> Mike Metcalf

> Tnanks for this Mike

> On the assumption that the BLOCKDATA initialisations are done at link-time,
> a linker should be smart enough to check the LIB file for BLOCKDATA without
> prompting with an EXTERNAL call. The only real use I can see in not
> automatically linking BLOCK data from a LIB file is that you can initialise
> COMMON from the host application with a separate BLOCKDATA; but this does
> not seem particularly "safe" programming to me.

> I guess the real answer is "FORTRAN 77 - know the rules and use with
> caution".

BLOCKDATA and loaders lead to a variety of problems. As you note the loader
does not find the BLOCKDATA because it does not read your mind very well.

Solutions include:

1. explicit inclusion of the BLOCKDATA. Note that this even permits you to
   have several differing versions of the blockdata in the library so that
   differing initializations are readily available. When used with a loader
   that is tolerant of COMMONs of differing sizes you end up with a quick
   way to adjust the sizes. Allocateable storeage is much better but not
   available in the past (i.e. F77).

2. partial prebinding in which the BLOCKDATA is bound to some other unit
   in the library which is known to be required.

3. the external reference trick which relies on the loader being able to
   resolve the EXTERNAL with a COMMON. This is fairly common by not a
   guaranteed solution. The scheme works so well that either the loader
   tends to get fixed to permit it or the compiler learns how to trick
   the loader into doing it.

4. permitting DATA for COMMON to be in other than a BLOCKDATA so end up with
   a nonstandard vendor specific extension.



Sat, 30 Aug 2008 22:21:46 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:

> On the assumption that the BLOCKDATA initialisations are done at link-time,
> a linker should be smart enough to check the LIB file for BLOCKDATA without
> prompting with an EXTERNAL call.

Why? Nothing tells it to. Just because there happens to be something in
the library that could sensibly be linked in, that doesn't mean that it
should be linked in. That's simply not how linkers work with libraries.
Period. They search libraries for things that have been requested. No
request = no load. You are probably thinking of a different model of a
library, where everything in the library is for one program. In fact, a
single library can support many programs and thus have many things in it
that are not used in any particular program.

This mostly isn't f77-specific. It is just how libraries work. The main
f77 specific isssues is that common blocks are allowed either with or
without initialization. There is nothing in the source code of the main
program or subprograms to tell which is intended. Thus there is nothing
to tell the linker whether or not you want this.

Please note also that the EXTERNAL statement thing is a hack. It is a
hack that is sort of endorsed by a published interpretation of the f77
standard, but if you read that interpretation carefully, it just says
that a compiler *MAY* give that meaning to such an EXTERNAL statement.
However, the standard gives no guarantee to the user on this. So it
might be that you put an EXTERNAL statement in and it still doesn't
link. Things like how to compile the code and how to use libraries are
outside the scope of the standard.

Another hack that sometimes works is to put the block data in the same
source file as something else that is loaded. This works on systems
where each source file makes a single "object" that is loaded as an
unbreakable whole.

Yet another hack I personally have used is to avoid direct
initialization of common, but instead to do the "initialization" in
executable code, basically substituting a subroutine for the block data
(and of course, calling the subroutine from somewhere). For arrays where
the DATA statement notation is particularly handy, I've been known to
make a local initialized array, which I then copy into the one in
COMMON. Ok, it wastes space, but the amount of space taken by anything
that I'm likely to have explicit DATA statements for just isn't going to
be enough to get e{*filter*}d about today. This was my preferred approach in
the later part of my f77 days, and it still is for those projects where
I am forced to use f77 for some external reason.

But basically, they are all hacks. I think that using f90 modules is a
far better approach.

--
Richard Maine                     | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov            |       -- Mark Twain



Sun, 31 Aug 2008 00:57:29 GMT  
 Lost BLOCKDATA initialisation in LIB files
I'd like to add one particular 'solution', but I think it is tied to
IBM's xlf90. You seem to be able to actually CALL a BLOCKDATA (I assume
that this is a kind of trick related to this load problem):

~> cat test.f
BLOCKDATA myblock
 COMMON/C/ I
 DATA I /1/
END BLOCKDATA
COMMON/C/ I
write(6,*) I
CALL myblock()
write(6,*) I
END
~> xlf90 -std=f95 test.f
** myblock   === End of Compilation 1 ===
** _main   === End of Compilation 2 ===
1501-510  Compilation successful for file test.f.

 1
 1

Joost



Sun, 31 Aug 2008 01:44:48 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:
> I'd like to add one particular 'solution', but I think it is tied to
> IBM's xlf90. You seem to be able to actually CALL a BLOCKDATA (I assume
> that this is a kind of trick related to this load problem):

> ~> cat test.f
> BLOCKDATA myblock
>  COMMON/C/ I
>  DATA I /1/
> END BLOCKDATA
> COMMON/C/ I
> write(6,*) I
> CALL myblock()
> write(6,*) I
> END
> ~> xlf90 -std=f95 test.f
> ** myblock   === End of Compilation 1 ===
> ** _main   === End of Compilation 2 ===
> 1501-510  Compilation successful for file test.f.

>  1
>  1

> Joost

There are some very sporting folks who noticed the details of what the
loader/linker/binder wants/tolerates as well as what the compiler
generates on their system and have encoded machine instructions
in binary/hexadecimal and then called the COMMON block. It makes for
a better story down at the bar with the boys and saves the annoyance
of using the assembler. This is extreme sport at its extreme!

Some loaders turn missing references into no-ops. Usually not helpful.
Perhaps that is the case here or maybe the compiler compiles just a
return to keep the loader happy. You note that it is a "solution" only
and is just for one specified compiler. CALL and EXTERNAL tend to provide
similar information about required components. The question is how/why
the call functions. I have dim memories of some folks who did this but
were careful to ensure that the call was never executed. There may even
have been some arcane explanation as to why they did not use an EXTERNAL
statement (like they had not seen it in the manual or it produced
slightly different information for the loader).

Having seen too many of these games I no longer use BLOCK DATA and have
a subroutine with the marvelous name of INIT in most programs.



Sun, 31 Aug 2008 02:57:37 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:

> CALL and EXTERNAL tend to provide
> similar information about required components....
> I have dim memories of some folks who did this [called a blockdata] but
> were careful to ensure that the call was never executed.

Sounds (dimly) familliar.

Quote:
> There may even have been some arcane explanation as to why they did not
> use an EXTERNAL statement

Just speculating, but one possibility that occurs to me is that some
compilers might have effectively done nothing with the EXTERNAL
declaration if it was never referenced - much like eliminating variables
that are declared but unused.

Quote:
> Having seen too many of these games I no longer use BLOCK DATA and have
> a subroutine with the marvelous name of INIT in most programs.

Me too, as noted in my other post. The exact name(s) vary, as I often
have multiple init_this and init_that subroutines, but same idea, and
they might all be wrapped in something like an init_everything. Well,
mostly I use modules and avoid common altogether, but when I need common
for some reason, initialization in a subroutine is my preferred
approach. It is hard to beat for guaranteed portability without fuss.

--
Richard Maine                     | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov            |       -- Mark Twain



Sun, 31 Aug 2008 03:14:23 GMT  
 Lost BLOCKDATA initialisation in LIB files
Hello,

<snip>

Quote:
>> There may even have been some arcane explanation as to why they did not
>> use an EXTERNAL statement

> Just speculating, but one possibility that occurs to me is that some
> compilers might have effectively done nothing with the EXTERNAL
> declaration if it was never referenced - much like eliminating variables
> that are declared but unused.

However, in 04-007, at [264:4-5], an external statement confirms
that a block data is part of a program.

I have had discussions with compiler writers on this point,
so I know not all compilers enforce this feature.  But it is
supposed to work.

<snip>

--
Cheers!

Dan Nagle
Purple Sage Computing Solutions, Inc.



Sun, 31 Aug 2008 03:50:11 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:

> However, in 04-007, at [264:4-5], an external statement confirms
> that a block data is part of a program.

Yes, but that sentence in the standard has almost no content. It does
not say that therefore this should cause the block data to be pulled out
of a library, etc., because the standard doesn't talk about that kind of
thing.

Note the "confirms" bit, which means that this isn't new information.
All this says is that if you have a block data of that name, you are
allowed to have such an external declaration and that shouldn't keep the
program from compiling and running. But it doesn't do anything
affirmative.

Note in particular the distinction between "confirms" and "specifies".
Such an external statement does not specify that. It can't because there
is no way to know that it refers to a block data. At best, one might
imagine that an external statement specifies that there is something of
that name in the program - maybe a procedure or maybe a block data. But
the only way for you to know that there is a block data in the program,
as opposed to some procedure of the same name, is to have it actually
loaded, by which time the external statement is just confirming what you
already know.

The word "confirms" is used several places in the standard, and always
in the same sense - when something is confirmed, that means that the
confirmation adds no new information. It is an allowed redundancy. At
times, it can be useful to confirm something for clarity or to force an
error in case what was intended to be a confirmation turns out to be a
contradiction instead. I know of no instances where confirmation imposes
a requirement on the compiler other than to accept the code.

--
Richard Maine                     | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov            |       -- Mark Twain



Sun, 31 Aug 2008 04:21:21 GMT  
 Lost BLOCKDATA initialisation in LIB files
Quote:


>>On the assumption that the BLOCKDATA initialisations are done at link-time,
>>a linker should be smart enough to check the LIB file for BLOCKDATA without
>>prompting with an EXTERNAL call.

> Why? Nothing tells it to. Just because there happens to be something in
> the library that could sensibly be linked in, that doesn't mean that it
> should be linked in. That's simply not how linkers work with libraries.

...
I think the confusion comes from people thinking of BLOCK DATA as a
definition for a data segment in the target object file. In that case,
loading the initialized data segment gives what you want. However, BLOCK
DATA is normally created as a subroutine that initializes allocated data.

Maybe it would be better if BLOCK DATA were restricted to defining data
segments in a way that would be converted to a data segment rather than
a subroutine. Do any compilers do that? Or is the specification such
that it has to be a subroutine?

Since BLOCK DATA is an initialization subroutine rather than a BLOCK of
DATA, it seems that an associating an initialization subroutine with a
module makes a lot of sense. Are there plans in F2008 to make an
automatically invoked init routine? It seems F2003 has a automatic
finalization but not automatic initialization. At least calling an init
routine is much more sane than figuring out how to hint the compiler
that it should call BLOCK-DATA routines.

Joe



Sun, 31 Aug 2008 06:29:54 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:

> I think the confusion comes from people thinking of BLOCK DATA as a
> definition for a data segment in the target object file. In that case,
> loading the initialized data segment gives what you want. However, BLOCK
> DATA is normally created as a subroutine that initializes allocated data.

Huh?

Quote:
> Maybe it would be better if BLOCK DATA were restricted to defining data
> segments in a way that would be converted to a data segment rather than
> a subroutine. Do any compilers do that? Or is the specification such
> that it has to be a subroutine?

Um, rather the opposite. Where did you get the impression that it was
anything at all like a subroutine? To the contrary, the usual
implementation *IS* more like just a data segment (translated into
whatever terminology fits the OS). I'd make exactly the opposite point,
that the specification allows it to look like some kind of automatically
called subroutine... but that nobody implements it that way (at least to
my knowledge).

Maybe you were mislead by the comments of Godon and myself. We didn't
say that block data was commonly implemented as subroutines. We said
that we use subroutines *INSTEAD* of block data.

Or do you actually know of any implementations where it really looks
like a subroutine? Blockdata was mentioned as being calable in xlf, but
it isn't clear to me what that actually implied for implementation.
Maybe that is a case, but if so, it is the exception.

Quote:
> Since BLOCK DATA is an initialization subroutine rather than a BLOCK of
> DATA, it seems that an associating an initialization subroutine with a
> module makes a lot of sense.

Since the premise is false, the conclusion doesn't follow. My comment
about modules was more along the line that with modules you could more
safely and probably do actual initialization instead of "faking" it with
a subroutine. Of course, there is often also a role for initialization
subroutines to do things that don't fit in the simple mold of normal
data initialization, but that's a different matter - related but
different.

Quote:
> Are there plans in F2008 to make an
> automatically invoked init routine? It seems F2003 has a automatic
> finalization but not automatic initialization.

Your question seems to confuse two other things here. You connected this
with modules, which don't have anything in particular to do with f2003
finalization. Finalization is tied to a derived type. Now it is true
that derived types are often (usually) implemented in modules, but that
is not relevant and just confuses matters because there are two distinct
questions.

1. Type-bound initialization routines. Yes, they not only have been
discussed, they were even in early drafts of f2003. However, they got
pulled because the version on the draft was woefully inadequate and
would have taken large amounts of work to properly integrate.
Initialization turns out to ba a lot more complicated than finalization,
fundamentally because initialization tends to need more options. Often
you want to say not just "initialize this", but more specifically
"initialize it this using that". For a trivial example from intrinsic
types, you might want to initialize an integar variable with the value
42; that 42 has to get into the process somehow. Finalization tends to
be much simpler in that "finalize this" is all you need to say.

Also, type-bound initialization was viewed as a dispensable nicety,
while finalization was a necessity to avoid memory leaks in some
senarios. Thus the initialization was both less important and more
difficult than finalization. That's a bad combination; it lost.

I'm not sure it permamently lost. Might come back again; I'm not
up-to-date on that.

2. Module initialization. That is a completely different subject, but
one that has also been discussed. At one point I was pushing for the
capability of having a module initialization procedure that was
"automatically" called as a consequence of loading the module, without
needing an explicit CALL statement or equivalent. I envisioned this as
something that could accomplish "nifty" things in conjunction with
polymorphism and dynamic dispatch. In particular, I envisioned being
able to add capabilities to a program just by loading in an extra module
without there having needed to be any explicit reference to the new
module in the old code. More detail would be out of place here. Some
vendors had implementation objections to that and it died. I'm not sure
whether or not it will stay dead forever, but that's the last status I
know about.

--
Richard Maine                     | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov            |       -- Mark Twain



Sun, 31 Aug 2008 07:18:28 GMT  
 Lost BLOCKDATA initialisation in LIB files
(snip about BLOCK DATA in libraries, and EXTERNAL)

Quote:
> I think the confusion comes from people thinking of BLOCK DATA as a
> definition for a data segment in the target object file. In that case,
> loading the initialized data segment gives what you want. However, BLOCK
> DATA is normally created as a subroutine that initializes allocated data.

I know they are data on OS/360, and I believe also on later (OS/390, z/OS)
systems also.  The linker hasn't changed that much over the years.

Actually, for OS/360 BLOCK DATA generates CSECT with the same name as
each COMMON block, but containing data instead of code.  (CSECT is what
executable code goes in.)  COMMON outside of BLOCK DATA generates COM
which allocates space but does not initialize it.  One effect of this is that
if COMMONs have different sizes the one in BLOCK DATA must be at least
as large as the largest one.  (I don't remember the rule for blank COMMON
in BLOCK DATA.)

I believe CSECT is also generated for static initialized data
in C and PL/I, and COM for uninitialized static in PL/I.

As far as I know, for DOS/windows and unix BLOCK DATA is also data,
with no executable code, though it might be that a return instruction
is generated just to take care of this problem.

(snip about executable BLOCK DATA)

-- glen



Sun, 31 Aug 2008 07:49:22 GMT  
 Lost BLOCKDATA initialisation in LIB files

Quote:


>>I think the confusion comes from people thinking of BLOCK DATA as a
>>definition for a data segment in the target object file. In that case,
>>loading the initialized data segment gives what you want. However, BLOCK
>>DATA is normally created as a subroutine that initializes allocated data.

> Huh?

>>Maybe it would be better if BLOCK DATA were restricted to defining data
>>segments in a way that would be converted to a data segment rather than
>>a subroutine. Do any compilers do that? Or is the specification such
>>that it has to be a subroutine?

> Um, rather the opposite. Where did you get the impression that it was
> anything at all like a subroutine? To the contrary, the usual
> implementation *IS* more like just a data segment (translated into
> whatever terminology fits the OS). I'd make exactly the opposite point,
> that the specification allows it to look like some kind of automatically
> called subroutine... but that nobody implements it that way (at least to
> my knowledge).

I got the idea from g77, where I first started serious FORTRAN-ing:

  "`g77' currently compiles a `BLOCK DATA' as if it were a `SUBROUTINE',"

But, on reading more carefully, it seems that it was done for f2c
compatibility, and as a hack to hint that you want to link in a block
data segment.

I thought the weakness of BLOCK DATA was that it needed a subroutine to
be called. But, I now realize that's not it at all. The problem is that
common blocks are always seen as external from program units, and an
actual instance of the common block is always implicit -- except in the
case of block data.

[snip]...

I'll comment on the INIT/FINI stuff later

THANKS, Joe



Sun, 31 Aug 2008 09:04:51 GMT  
 
 [ 17 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Lost Lib files - lost source

2. looking lost file CLD.LIB ver 5.2 Clipper

3. Editing LIB Files to Change Functions Within LIB Files

4. I lost my library CT.LIB for Clipper 5.01

5. Need old lib file - expand.lib

6. calling winapi without lib or source for winapi lib files

7. Statically Linking tcl.lib and tk.lib into a standalone .exe file

8. Save and Blockdata (re: Elegant Common)

9. Dump Entry Points In .LIB files or .DLL Files

10. VMS LIB$ copying file a file in FORTRAN

11. pretty-printing (lose, lose)

12. ABC File closes when window lose focus

 

 
Powered by phpBB® Forum Software