[comp.software-eng] Question Re: Configuration Management

breck@aimt.UUCP (Robert Breckinridge Beatie) (02/12/88)

I've been having a discussion with my boss about how to re-partition the
source for a small package.  When we failed to convince each other to our
respective points of view my boss kind of ended the argument by declaring
that "in his experience" the problems with my approach outweighed the
benefits.  Since I don't have enough experience of my own to effectively
counter such sound logic, I thought I'd ask the net.

Basically the argument is over one question: "Is it acceptable to have
more than one 'call interface' per source file or not?"  For our purposes
a 'call interface' is defined as a non-static function in a C source file.
My boss' position is that having more than one 'call interface' per source
file causes so many "configuration management" problems that it outweighs any
benefits.

Now I've never heard this recommendation before.  Nor have I ever seen
(non-trivial) software that only had one 'call interface' per source file.
 I've gone looking through the source to all our products.  I've looked
through some of the software from comp.sources.unix.  I've also looked through
libc.a and in every case there were object files with more than one extern
function definition.  But still, I don't have any real experience with
"configuration management" so I have to ask the experts for the benefit of
their experience.

So how about it?  What horrible CM problems does having more than one
'call interface' per source file cause?  Has anyone had any such problems?
I'd appreciate any horror stories, anecdotes, or opinion.
-- 
Breck Beatie
{uunet,ames!coherent}!aimt!breck
"Sloppy as hell Little Father.  You've embarassed me no end."

daryl@ihlpe.ATT.COM (Daryl Monge) (02/14/88)

In article <497@aimt.UUCP>, breck@aimt.UUCP (Robert Breckinridge Beatie) writes:
> Now I've never heard this recommendation before.  Nor have I ever seen
> (non-trivial) software that only had one 'call interface' per source file.

I haven't either.

> So how about it?  What horrible CM problems does having more than one
> 'call interface' per source file cause?

None, unless of course the modules are unrelated.  For example, wouldn't
you want the insert, delete, and search functions for a hash table
implementation in a single file "hash.c" for readability and maintenance?
Did you ask what those problems were, or would that be dangerous to your
career?

We strive for a set of product goals that consist of a set of required
standards and recommended guidelines.  Each person or project should
establish these to their own satisfaction.  But avoid nitpicking.

In this particular case, we have requirements of maximum lines per module,
but only a goal of functions per file.  The above managers requirement
does seem restrictive to me.

Daryl Monge				UUCP:	...!ihnp4!ihcae!daryl
AT&T					CIS:	72717,65
Bell Labs, Naperville, Ill		AT&T	312-979-3603

g-rh@cca.CCA.COM (Richard Harter) (02/14/88)

In article <497@aimt.UUCP> breck@aimt.UUCP (Robert Breckinridge Beatie) writes:
>
>Basically the argument is over one question: "Is it acceptable to have
>more than one 'call interface' per source file or not?"  For our purposes
>a 'call interface' is defined as a non-static function in a C source file.
>My boss' position is that having more than one 'call interface' per source
>file causes so many "configuration management" problems that it outweighs any
>benefits.
>
>So how about it?  What horrible CM problems does having more than one
>'call interface' per source file cause?  Has anyone had any such problems?
>I'd appreciate any horror stories, anecdotes, or opinion.


	There are a number of issues involved here.  The following may be
what your boss has in mind.  If every file has exactly one entry point
and that entry point has the same name as the file (with the extension
stripped off) then life becomes simpler in a number of respects.  When you
see function foo in some source code you know that it can be found in file
foo.c [more or less -- it may be a macro or in a system library or ...].
Similarly, if the linker comes up with "foo not found", you know that
you need to include foo.o to the list of files loaded.  [Again, foo
may be a data global -- most linkers are reticent about such details.]

	The classical way to describe a hardware configuration is use an
indented tree listing, e.g.

	System
	  Sub system 1.
	    Component 1.1
	    Component 1.2
	  Sub system 2.
	    Component 2.1
	    ...

When we talk about software, the question is, "are the compenents procedures
or files".  If we are talking about program structure, the answer is
"procedures".  However the components managed are usually files.  If we
follow the one procedure, one file rule there is no problem.  Suppose,
however, that we have packaged several procedures into one file, e.g.
components 1.1 and 2.1 are contained in the same file.  Then the single
file is shared by several subsystems.  This makes for complications.

	Actually, of course, the problem is there even if we follow the
one file, one procedure rule.  To see why, let me take an example from
hardware.  The B-999 bomber has a hydraulic subsystem and a wing attitude
control subsystem.  The wing attitude control subsystem uses a hydraulic
lifter.  This component is functionally part of two different subsystems.
A good CM system (hardware or software) must be able to deal with 
multiple interlocking subsystems.

	Version control is an important part of CM.  Since terminology
is often confused in this area, let me distinguish between file version
control, and configuration version control.  Tools such as SCCS and RCS
are file version control tools.  If you build a CM version control system
on top of file version control tools you run into problems if the elements
of your configuration are procedures.  These problems can be addressed,
but things can get sticky if they aren't.

	As to best practice, my rule is that the one file/one procedure
rule should be followed _except_ when you have a group of procedures which
forms an atomic package.  In that case, the file should bear the name of
one of the procedures in the package.  There are a number of principles
that one should follow in setting up such packages, but that is another
issue.

	I hope this is some help.
-- 

In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die.
	Richard Harter, SMDS  Inc.

jameson@calgary.UUCP (Kevin Jameson) (02/17/88)

The basic problem with keeping several procedures in one physical file
is that it becomes more difficult (both conceptually and physically) to
manipulate individual procedures.  If you know that you never have
to treat a particular procedure as an individual unit, then placing
a group in one file makes more sense (eg, as with Hash_get, Hash_put, etc).
Sometimes the grouping will be forced if all related procedures require
statically allocated (ie, private) declarations.

For example, if you have one procedure per file, you can replace individual
procedures easily if need be, and are not generally penalized when you
must manipulate related groups.  The functions in the calling tree are
also more accessible (at the operating system file level vs. having to
manually search each physical file).  Translation to other languages
is made easier when you don't have to deal with many functions per 
file.  Software tools are much easier to construct for the one-proc-per-file
model too.  File i/o cost in the editor is considerably improved because
you only have to deal with small files.

We liked the one-proc/file method so much that one person in our group
wrote a a tool to combine many individual procedures into one larger
file for compilation and linking purposes (the linker could only handle
150 physical object files).  Each procedure is thus maintained in its
own file, and then it is combined with related procedures to get by
the linker restriction.

On the other hand, the one-proc/file method has some disadvantages.  The
physical file namespace can get crowded when several hundred procedures
are in the program.  The combination step takes a bit more time.  Global
name changes to related procedures take more effort.  

In our view (experience) the one-proc/file method far outweighs any
extra hassle because you can manipulate procedures at the individual
procedure level.

Kevin {ihnp4,ubc-vision}!alberta!calgary!vaxb!jameson

pete@wor-mein.UUCP (Pete Turner) (02/18/88)

In article <2640@ihlpe.ATT.COM> daryl@ihlpe.ATT.COM (Daryl Monge) writes:
>
>None, unless of course the modules are unrelated.  For example, wouldn't
>you want the insert, delete, and search functions for a hash table
>implementation in a single file "hash.c" for readability and maintenance?

No, personally I wouldn't. I would put the files insert.c, delete.c
and search.c (or HS_insert.c, HS_delete.c and HS_search.c) in the directory
"hash". I just don't see any advantage in putting more than one function
in each file.

In this case, I think the boss has a good point. I've dealt with CM issues
on large projects ( > 100K lines), involving a dozen or more developers,
and things were a lot easier once we decided to have only one function
per file. Also, it is a good idea to provide the "client" with a separate 
include file for each interface to a given "service". For example, if you're 
using a storage service (maybe a hash table implementation, maybe some other,
you don't need to know as long as it performs to your reqirements) and you
want to use the delete function, assuming you're writing in C, just include
ST_delete.h and call ST_delete(....). ST_delete() may be a function call or
it may be a macro - why should you care, as long as it works?

hull@dinl.uucp (Jeff Hull) (02/18/88)

You do run into some problems when you need to update one procedure
in a multi-procedure file.  Tracking exactly what changed and why
is one such problem.  (This one is typically handled via comments
embedded in the source code; not an elegant solution, in my opinion.)

When you are controlling documentation, the multiple "procedures" in
one file approach drives you to send out updates that include many
more change pages that would otherwise be necessary, for example.

There are other problems that require mucho context definition to 
explain.

Why would you (ever) want to put more than one "procedure" in a file
anyway.  Now that we have <make> and similar utilities, it is very
simple to (re-)compile programs contained in many files, so why not
put one procedure in one file?


-- 
Jeff Hull		...!hao!dinl!hull
1544 S. Vaughn Circle	303-750-3538	It was great when it all begaaaaan,
Aurora, CO 80012			I was a regular <USENET> faaaan, ....

pokey@well.UUCP (Jef Poskanzer) (02/18/88)

In the referenced message, breck@aimt.UUCP (Robert Breckinridge Beatie) wrote:
> Now I've never heard this recommendation before.  Nor have I ever seen
> (non-trivial) software that only had one 'call interface' per source file.
>
> So how about it?  What horrible CM problems does having more than one
> 'call interface' per source file cause?

One problem peculiar to Unix is caused by the brain-damaged library
system.  Let's say you have a .c file with 20 marginally related
routines in it.  You make it into a library, then write a program
that uses only one of those routines.  When you link it, guess what
happens?  All 20 routines get pulled into your executable.

Until someone fixes this, perhaps with a utility to dissect an object
file into N separate object modules, it makes sense to put as few
routines as is reasonable into each source file.
---
Jef

              Jef Poskanzer   jef@lbl-rtsg.arpa   ...well!pokey
 "She was a girly girl and they were true men, the lords of creation, but she
        pitted her wits against them and she won." -- Cordwainer Smith

mjl@ritcv.UUCP (Mike Lutz) (02/19/88)

In article <188@dinl.mmc.UUCP> hull@dinl.UUCP (Jeff Hull) writes:
>Why would you (ever) want to put more than one "procedure" in a file
>anyway.  Now that we have <make> and similar utilities, it is very
>simple to (re-)compile programs contained in many files, so why not
>put one procedure in one file?

The issue is one of packaging based on abstract interfaces.  If I write
a symbol table handler, with Initialize, Lookup, Enter, Update, and
Delete operations, I want the implementation details to be hidden, especially
the details of the data organization I choose.  The natural package in C
is one where the implementation "secrets" are kept as static global
data structures (and internal support routines are static as well, to
avoid name clashes with the client).  To do this, of course, the visible
operations must be in the same file at compile time -- and I argue
that they form a unified abstraction that *should* be in one file.  If
you change the internal data structure details (or create alternate
versions), you'll find your configuration management problems
*decrease* with such packaging.

And, for the person who complained about the brain damaged Unix linker and
librarian: most linkers I've encountered have the same restriction.
The library contains object modules, possibly with multiple entry points,
and if you reference one you get them all.  It's damn difficult to pull
apart an object module and decide which bytes you need and which ones
are extraneous.  The Unix linker/librarian may not set the world on fire
with it's snazzy features, but it most certainly is state of the practice.

Mike Lutz
...rutgers!rochester!ritcv!mjl


-- 
Mike Lutz	Rochester Institute of Technology, Rochester NY
UUCP:		{allegra,seismo}!rochester!ritcv!mjl
CSNET:		mjl%rit@csnet-relay.ARPA

chris@metavax.UUCP ( PSA) (02/19/88)

In article <5257@well.UUCP> pokey@well.UUCP (Jef Poskanzer) writes:
 
>One problem peculiar to Unix is caused by the brain-damaged library
>system.  Let's say you have a .c file with 20 marginally related
>routines in it.  You make it into a library, then write a program
>that uses only one of those routines.  When you link it, guess what
>happens?  All 20 routines get pulled into your executable.
 
I hate to say this, but why isn't such a linker the standard on Unix?
It seems to me that if Unix is _the_ system for programmers, as it has
been described to me several times, why does this idiocy exist?  What
good is a linker that is so stupid, other than it's all there is?  One
supposed Unix guru tried to tell me that this actually made the linker
smarter!!!!!!   (I replied by asking how he removed his lobotomy scar.)

    ------ 
   /MM/\MM\          META SYSTEMS, LTD.
  /MM/  \MM\         315 E. Eisenhower
 /MM/ /\ \MM\            Suite 200
 ===  ==  ===       Ann Arbor, MI  48108
 \SS\ \/ /SS/
  \SS\  /SS/        Chris Collins, Senior Programmer
   \SS\/SS/
    ------

chris@metavax.UUCP ( PSA) (02/20/88)

In article <2984@metavax.UUCP> chris@metavax.UUCP (Chris Collins) writes:
  
>I hate to say this, but why isn't such a linker the standard on Unix?
                             ^^^^^
Ok, I'm a moron too.  This should be "is", not "isn't".  I'm a programmer,
not an accomplished writer.

    /MM/\MM\          META SYSTEMS, LTD.
   /MM/  \MM\         315 E. Eisenhower
  /MM/ /\ \MM\            Suite 200
  ===  ==  ===       Ann Arbor, MI  48108
  \SS\ \/ /SS/
   \SS\  /SS/        Chris Collins, Senior Programmer
    \SS\/SS/
     ------

pokey@well.UUCP (System Operator) (02/21/88)

In the referenced message, mjl@ritcv.UUCP (Michael Lutz) wrote:
}And, for the person who complained about the brain damaged Unix linker and
}librarian: most linkers I've encountered have the same restriction.

Then I guess you haven't encountered that many linkers.  The VAX/VMS linker
does this right.  The RSX-11 linker does this right.  The TOPS-20 linker
does this right.  Even the god damned PDP-8 linker running FORTRAN-II did
this right.

}                 The Unix linker/librarian may not set the world on fire
}with it's snazzy features, but it most certainly is state of the practice.

It most certainly is not.  It was already obsolete when it was written,
and it hasn't gotten any better in the intervening decade.
---
Jef

              Jef Poskanzer   jef@lbl-rtsg.arpa   ...well!pokey
              ...on the other hand, perhaps we're all on drugs.

dc@gcm (Dave Caswell) (02/22/88)

=The basic problem with keeping several procedures in one physical file
=is that it becomes more difficult (both conceptually and physically) to
=manipulate individual procedures.  If you know that you never have
=to treat a particular procedure as an individual unit, then placing
=a group in one file makes more sense (eg, as with Hash_get, Hash_put, etc).
=
The computer system we just finished is 73,000 lines.  It is in 128 source
files and has 1874 functions.  I couldn't imagine the complexity of having
1874 separate files.   How could a person possibly tell what is related to 
what?   Each file reads from top to bottom like a book.  We weren't at all
concerned with time to load the editor.    The project took 3 people-years
or over 250,000$.    The time was spent debugging, designing, and learning
the application.  It wasn't spent waiting for emacs to startup.

noise@eneevax.UUCP (Johnson Noise) (02/22/88)

In article <2984@metavax.UUCP> chris@metavax.UUCP (Chris Collins) writes:
>In article <5257@well.UUCP> pokey@well.UUCP (Jef Poskanzer) writes:
> 
>>One problem peculiar to Unix is caused by the brain-damaged library
>>system.  Let's say you have a .c file with 20 marginally related
>>routines in it.  You make it into a library, then write a program
>>that uses only one of those routines.  When you link it, guess what
>>happens?  All 20 routines get pulled into your executable.
> 
>I hate to say this, but why isn't such a linker the standard on Unix?

	NO! NO! NO!

>
>It seems to me that if Unix is _the_ system for programmers, as it has
>been described to me several times, why does this idiocy exist?  What
>good is a linker that is so stupid, other than it's all there is?  One
>supposed Unix guru tried to tell me that this actually made the linker
>smarter!!!!!!   (I replied by asking how he removed his lobotomy scar.)
>

	Get a clue!  The linker will pull in whole object modules which
have been put in a library.  If one seperates functions into several
object modules and then creates a library,  the desired effect of the
so called "optimizing linker" is acheived.  All the systems I have seen
work this way.  Don't criticize something you don't understand!

	BTW Unix is THE system, for programmers or otherwise, it does
have one obvious drawback: it assumes the user is competent.  The idiocy
you speak of is not with system!  A lobotomy in your case is not necessary.

ok@quintus.UUCP (Richard A. O'Keefe) (02/22/88)

In article <2984@metavax.UUCP>, chris@metavax.UUCP ( PSA) writes:
> In article <5257@well.UUCP> pokey@well.UUCP (Jef Poskanzer) writes:
>  
> >One problem peculiar to Unix is caused by the brain-damaged library
> >system.  Let's say you have a .c file with 20 marginally related
> >routines in it.  You make it into a library, then write a program
> >that uses only one of those routines.  When you link it, guess what
> >happens?  All 20 routines get pulled into your executable.
>  
> I hate to say this, but why isn't such a linker the standard on Unix?
> It seems to me that if Unix is _the_ system for programmers, as it has
> been described to me several times, why does this idiocy exist?  What
> good is a linker that is so stupid, other than it's all there is?  One
> supposed Unix guru tried to tell me that this actually made the linker
> smarter!!!!!!   (I replied by asking how he removed his lobotomy scar.)
> 
Why not RTM?  If you want to be able to pull individual functions out of
a library, ***YOU CAN***.  What you do is
	cc -c foo.c baz.c ugh.c		# one file for each CLUSTER
	ar q lib.a foo.o baz.o ugh.o	# collect the .o files
	ranlib lib.a			# build a table of contents
Now, if you do
	cc user.c stuff.c lib.a
you will not get the "ugh" cluster out of lib.a unless you need it.

Now, why can't you do this with a single file such as what
	cc -c ugh.c
gives you?  Not because the linker is stupid, but because it is in
general impossible.  Suppose you have

	cat <<EOF >foo.c
	static f(...){...}
	static g(...){...}
	h(...){... f() ...}
	i(...){... g() ...}
	EOF

If you use h(), you'd like just h() and f(), right?  But how is the
linker supposed to know that h() uses f()?  The compiler has to tell
it, and UNIX compilers don't do that.  In fact, there's no law that
says a smart compiler can't notice that h() and i() look pretty similar
and decide to share some code between them.  Indeed, in the special
case of string literals, there are lots of C compilers that DO this.

The thing is, if you put 20 functions in one file (and nobody is
twisting your arm to do this, there is nothing at all stopping you
putting them each in its own file), you are telling the C compiler
"I *chose* to put these together, I *want* them loaded as a unit,
and if you can do something clever because of that, fine!".

Instead of flaming the UNIX linker, why not tell us the name of a
linker that does what you want?  Before doing that, though, you'll
want to check that it doesn't limit this facility to Fortran...

kers@otter.hple.hp.com (Christopher Dollin) (02/22/88)

"pete@wor-mein.UUCP (Pete Turner)" says (quoting)
|>
|>None, unless of course the modules are unrelated.  For example, wouldn't
|>you want the insert, delete, and search functions for a hash table
|>implementation in a single file "hash.c" for readability and maintenance?
|
|No, personally I wouldn't. I would put the files insert.c, delete.c
|and search.c (or HS_insert.c, HS_delete.c and HS_search.c) in the directory
|"hash". I just don't see any advantage in putting more than one function
|in each file.

I'd go for "one-datatype-per-file". Spliting the files up using directories is
just a hack for controlling a growing namespace; NO existing language that I
know of has a decent solution for this (and if *you* know of one that does,
**please** let me know!).

To counts against splitting in the hash example (and similars):

(a) When a developer is given the job of updating the hashing datatype, da[1]
must acquire multiple files. Da must update them in lock-step. More potential
for confusion arises because the atomicity is too low.

(b) The split modules must communicate. Typically this means that they must
share *private* header files. That's at least one more file in the system, and
this one's not even a real module!

And a personal preference:

When *I'm* the developer, I prefer my datatypes in files, not the components.
The components my be only a few lines long. Splitting them into separate files
gives me no benefit; I have to think of filenames for the components.

This is especially grocid because the Unix[2] I'm using, HP-UX, is s SysV
derivative that is still stuck with 14-character filenames. Now remove two
chars for the suffix (that's the MINIMAL suffix, ok). Now remove another two
for the ",v" if you're using RCS. Hm. Now remove 4 for the "ved_" prefix
(just a random example ...). Hm. What name was that? "comment"? Damn.




Regards,
Kers                                    | "Why Lisp if you can talk Poperly?"

pls@sortac.UUCP (Pat Sullivan) (02/22/88)

In article <213@ritcv.UUCP> mjl@ritcv.UUCP (Michael Lutz) writes:
 >The issue is one of packaging based on abstract interfaces ...
 >     a unified abstraction ... *should* be in one file.
I agree.

 >The library contains object modules, possibly with multiple entry points,
 >and if you reference one you get them all.
                                  ^^^^^^^^
This is true, but the statement is not entirely clear: if you reference
one of the entry points in an *OBJECT*, even if you just refer to a global
variable declared in an object, you get the entire object.  You do not
automatically get all the objects in the library (archive).
This is one more reason to limit the contents of an object to only those
that are tightly related.

 >Mike Lutz ...rutgers!rochester!ritcv!mjl

===================================================================
Pat Sullivan - {gatech|akgua|ihnp4}!sortac!pls - voice 404-257-7382

chris@metavax.UUCP ( PSA) (02/22/88)

Also, the IBM VM/CMS linker does this right, and the Unisys (Sperry)
1100 series linker does this right.

Chris Collins

marc@apollo.uucp (Marc Gibian) (02/23/88)

In article <213@ritcv.UUCP> mjl@ritcv.UUCP (Michael Lutz) writes:
>the details of the data organization I choose.  The natural package in C
>is one where the implementation "secrets" are kept as static global
>data structures (and internal support routines are static as well, to
>avoid name clashes with the client).  To do this, of course, the visible
>operations must be in the same file at compile time -- and I argue
>that they form a unified abstraction that *should* be in one file.  If

This is simply one of the limitations of the c language which should be
considered when going through the language selection process.  If
strict configuration management is highly valued in your project, then
this becomes a significant vote -AGAINST- c.

It seems that very few projects go through a language selection process.
Instead, a language is chosen because it is the -IN- language.  I believe
that if more attention were paid to this issue, there would be fewer
cases of people trying to make particular languages do what they just
plain can not do, or can not do well.

c is a good language for many projects.  But it tends to get into trouble
as the size of a project grows.  There have been many fine articles on
this subject and I do not intend to write my own here.  I simply want
to point out that there are many projects out there using c that
probably should be using some other language.  And this results in
a great deal of agony for the engineers working on these projects.

Marc S. Gibian
email:  marc@apollo.UUCP

UH2@PSUVM.BITNET (Lee Sailer) (02/23/88)

How does this "smart linker" business tie into the "shared libraries"
in Unix V.3.  As I understand it, (1) when I need a module, the whole
library is loaded, but (2) when another program needs a module from
the library, it shares the core image that is already in memory.

So, for example, at any moment, there is only one copy of all the stdio
(that's standard input-output in Unix-speak) stuff in memory at any given
moment, and all programs that need it share.  (This also makes the
executables smaller and saves disk space and load time.)

                                     Just asking,       Lee

karenc@amadeus.TEK.COM (Karen Cate;1502;92-734;LP=A;60kC) (02/24/88)

In article <188@dinl.mmc.UUCP> hull@dinl.UUCP (Jeff Hull) writes:
>
>Why would you (ever) want to put more than one "procedure" in a file
>anyway.  Now that we have <make> and similar utilities, it is very
>simple to (re-)compile programs contained in many files, so why not
>put one procedure in one file?
>-- 
>Jeff Hull		...!hao!dinl!hull
>1544 S. Vaughn Circle	303-750-3538	It was great when it all begaaaaan,
>Aurora, CO 80012			I was a regular <USENET> faaaan, ....

I assume by "procedure" you are referring to a single "C" function (or 
its equivalent).  I think this is another case of the law of diminishing 
returns.  If you have three procedures, each at least a "screen-ful" long,
then, yes, putting them in separate files makes sense.  However, when you
start looking at fourty, or so, procedures (especially when most of them 
are only a few lines long), individual files start working against you.
Add in complex interrelationships, and a liberal dose of global variables
for good measure, and you have a sure fire recipe for a massive headache.

Say, for instance, you want to change the passed parameters of one of your
procedures that is called often.  Instead of being able to use vi to find
all occurances for you, you will have to edit each file indiviually.  And
instead of changing one file, you have now changed dozens in one fell 
swoop.  Documenting that wouldn't be any fun either.  

My projects, so far, have been relatively autonomous, so I haven't had to 
document changes as rigorously as others may have had to (all I've been
required to do is document the revisions I check into RCS).

But, then again, every once in a while, I've been known to use a goto...

Karen A. Cate
Tektronix Inc, Beaverton, OR

tektronix!amadeus!karenc

daveb@geac.UUCP (David Collier-Brown) (02/24/88)

  Gentlebeings,
	Unix is not the be-all and end-all of creation.
	Unix is just better IN THE MAIN than its competition.
  Now, on to the substance of the discussuion:

In article <213@ritcv.UUCP> mjl@ritcv.UUCP (Michael Lutz) writes:
>And, for the person who complained about the brain damaged Unix linker and
>librarian: most linkers I've encountered have the same restriction.
>The library contains object modules, possibly with multiple entry points,
>and if you reference one you get them all.  It's damn difficult to pull
>apart an object module and decide which bytes you need and which ones
>are extraneous.  The Unix linker/librarian may not set the world on fire
>with it's snazzy features, but it most certainly is state of the practice.


In article <2984@metavax.UUCP> chris@metavax.UUCP (Chris Collins) writes:
>	BTW Unix is THE system, for programmers or otherwise, it does
>have one obvious drawback: it assumes the user is competent.  The idiocy
>you speak of is not with system!  A lobotomy in your case is not necessary.

   Both Mike (politely) and Chris (substantially less so) miss the
point that the Unix linker was a conscious cheap-and-dirty.  The Multics
system avoided the whole IDEA of static linkers[1], and most if not
all commercial systems not derived from Unix have better linkers.
Good Lord, the IBM /360 had a better linker than Unix! (And I
wouldn't recommend the /3sickly and its linker to my worst enemy).  

   In order to learn C, a non-unix programmer of my acquaintance
ported a subset compiler (Ron Cain's Small C), and taught it to
generate code for his assembler/linker set, placing each function in
a linkable "procedure record", and emitting "symref records" for all
externally required datums of the function, including a symref to a
(specially named) record which contained the static data for the
module (ie, the file-level statics).  

  Not hard at all.  A suitable project for learning the language...

In pseudo-linkeese:
DSECT _.filename
	DW 1	    ; static int foo; /* A file-level static */
SYMDEF _function
CSECT _function
	LD A1,Sp    ; function(p,q) char *p, *q; {
	LD D1,_.filename+0 ; if (foo) {
	...
SYMREF _.filename

--dave (those who know not history.... piss me off) c-b

[1] It had a thing called "binder", which produced
    almost-fully-resolved modules, more or less for use as
    efficiently-loadable public libraries.
-- 
 David Collier-Brown.                 {mnetor yunexus utgpu}!geac!daveb
 Geac Computers International Inc.,   |  Computer Science loses its
 350 Steelcase Road,Markham, Ontario, |  memory (if not its mind) 
 CANADA, L3R 1B3 (416) 475-0525 x3279 |  every 6 months.

alanm@dvlmarv.UUCP (Alan Matsuoka) (02/25/88)

In article <679@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>In article <2984@metavax.UUCP>, chris@metavax.UUCP ( PSA) writes:
>
>Now, why can't you do this with a single file such as what
>	cc -c ugh.c
>gives you?  Not because the linker is stupid, but because it is in
>general impossible.  Suppose you have
>
>	cat <<EOF >foo.c
>	static f(...){...}
>	static g(...){...}
>	h(...){... f() ...}
>	i(...){... g() ...}
>	EOF
>
>If you use h(), you'd like just h() and f(), right?  But how is the
>linker supposed to know that h() uses f()?  The compiler has to tell
>it, and UNIX compilers don't do that.  

Yes, but only when the loader text  is defined in the UNIX tradition.
The problem here is the fact that all symbols and their references
are defined relative to a single compilation unit. If the loader text
contained directives ( like many other systems ) that would allow
you to define seprarately named sections, then it isn't too
hard to write a linker that can  accomplish the same thing as having
separate files. The problem is really one of granularity.

I suppose that it wouldn't too hard to then build the static calling
graph of the code ( why not ? Gprof can do it ), sort the addresses
and rearrange the code during the final writing phase to
allow for better locality.

The other issue is that in the context of UNIX systems a lot
of people don't really care if there is some dead code loaded or not.
In the case of a heavily loaded system on a small machine, I WOULD
care but in view of the fact that horsepower is getting cheaper and
memory even more so it becomes less of an issue.

On the other hand, I can remember somebody else pointing out that
if you can improve the execution time of a program running on something
like a heavily loaded 3090 by 1% , then you free up enough MIPS to
equal 100 PC's ( or something like that).

> In fact, there's no law that
>says a smart compiler can't notice that h() and i() look pretty similar
>and decide to share some code between them.  Indeed, in the special
>case of string literals, there are lots of C compilers that DO this.

And in some cases code as well. As I can recall, some experimental
code space optimizers can look at the entire Hierarchical directed
graph of a compilation unit, find the common subgraphs, create
the appropriate functions and procedures and their calls
and build a program that runs in a smaller code space.
Sorry, I don't know of any existing C compilers that will do this.
The one that I saw was written at a university for Pascal and it was nowhere
near to becoming a production compiler.

sommar@enea.se (Erland Sommarskog) (02/25/88)

Pete Turner (pete@wor-mein.UUCP) writes:
>In article <2640@ihlpe.ATT.COM> daryl@ihlpe.ATT.COM (Daryl Monge) writes:
>>None, unless of course the modules are unrelated.  For example, wouldn't
>>you want the insert, delete, and search functions for a hash table
>>implementation in a single file "hash.c" for readability and maintenance?
>
>No, personally I wouldn't. I would put the files insert.c, delete.c
>and search.c (or HS_insert.c, HS_delete.c and HS_search.c) in the directory
>"hash". I just don't see any advantage in putting more than one function
>in each file.

As this discussion have continued, I'm getting quite convinced that the
issue is quite related to the language in use. Some language may support
one of the different approaches better than the other. First of all the
language must be modular at least in some sense. In standard Pascal you
would have to put the whole project in one file :-)

I have worked a good deal with EriPascal, which is a Pascal extention
by a famous Swedish telephone company with modulariztion and real-time
features, reminding of Modula-2. Anyway, EriPascal does not allow variables
to be exported, so the hash table must in be one module.

In Ada both flavours are available, although I would recommend to have
them in all in one file as a package, this is the natural Ada approach.
Specifically this is very useful, when constructing a generic unit.
Note, however, that Ada permits procedures in a package to be separate,
which is the way to go when the procedure gets big.

As for C, which have been mentioned most, one procedure - one file
may be better, but since I don't know C I don't really have any opinion.

Generally I think that modules should be kept small in size, just
as they are structured in some way. Typing DIR and getting 120
source files listed is just a night mare. As Pete pointed out: put
related files in a directory.
-- 
Erland Sommarskog       
ENEA Data, Stockholm        
sommar@enea.UUCP           "Souvent pour s'amuser les hommes d'equipages
                            and it's like talking to a stranger" -- H&C.

UH2@PSUVM.BITNET (Lee Sailer) (02/25/88)

In article <3a7488cf.fed5@apollo.uucp>, marc@apollo.uucp (Marc Gibian) says:
>
>c is a good language for many projects.  But it tends to get into trouble
>as the size of a project grows.  There have been many fine articles on
>this subject and I do not intend to write my own here.  I simply want
>to point out that there are many projects out there using c that
>probably should be using some other language.  And this results in
>a great deal of agony for the engineers working on these projects.
>

SAS is a million lines of source, and is written in C, though I believe
it is a traslation from the original PL/1.  They must have some extra
tools they use--are they homebrew or commercial?

pokey@well.UUCP (Jef Poskanzer) (02/26/88)

This discussion is getting fairly tedious, but I guess it's worth one
more posting, since after all, I'm Right.

Recap: I pointed out that the Unix linker includes all the routines that
were compiled from one file if any single routine from that file is referenced.
Since other linkers are smart enough to include just the desired routine,
this means that the Unix linker is brain-damaged.  A number of people then
stated that it's IMPOSSIBLE for a linker do to what I claim all reasonable
linkers do.  None of these people bothered to TEST their assertion.  Some
of them were not particularly polite, either.  I guess I offended them by
daring to suggest that Unix isn't Lord God King Operating System.

Appended you will find a transcript showing the VAX/VMS linker doing
exactly what I claimed it does.  I'm using K&P's Software Tools, and
I've made everything nice and verbose so you can see exactly what's
going on.  I first compile a library from a single source file that
contains 14 routines and some global data structures.  Then I compile
a program that uses the library, and generate a linkage map so you
can see that only 3 routines from the library are included.

Moral of the story: just because you can't figure out how to do something
doesn't mean other people can't.  Moral 2: no matter how loudly and
forcefully you state your opinions, they don't become facts until you
test them.

If anyone still wants to dispute this issue, please send the discussion
to talk.bizarre where it belongs.  It stopped being about software
engineering some time ago.
---
Jef

              Jef Poskanzer   jef@lbl-rtsg.arpa   ...well!pokey


% rc -v -b src/rndlb
ratp1 src/rndlb >/tmp/t174411.r4
ratp2 /tmp/t174411.r4 >/tmp/t174358.f
rm /tmp/t174411.r4
$ fortran rtsgvx$dra0:[tmp]t174358.f-
/obj=rtsgvx$dra0:[tmp]t174395.o/nolist
rm lib/rndlb
$ library /create -
rtsgvx$drc2:[jef.lib]rndlb. -
rtsgvx$dra0:[tmp]t174395.o
rm /tmp/t174358.f
rm /tmp/t174395.o
% 
% 
% lslib lib/rndlb
rnd
rndbin
rndbta
rndchi
rndexp
rndf
rndgeo
rndini
rndint
rndnor
rndpoi
rndseq
rndt
rnduni
% 
% 
% rc -v -c src/phoon
ratp1 src/phoon >/tmp/t231258.r4
ratp2 /tmp/t231258.r4 >/tmp/t231194.f
rm /tmp/t231258.r4
$ fortran rtsgvx$dra0:[tmp]t231194.f-
/obj=rtsgvx$drc2:[jef.lib]phoon./nolist
rm /tmp/t231194.f
% 
% 
% cat phoon.tmp
[.lib]phoon.
[.lib]rndlb./libr
rt_misc_lib:dtlb./libr
rt_usr_lib:library./libr
% 
% 
% dcl link /map /brief /executable=[.bin]phoon. phoon.tmp /options
% 
% 
% bin/phoon
                        ------.
                         . .   `--.
                         .       . `-.
                           @@@@@      `-.
                          @@@@@@@   .    \
                          @@@@@@@       . \.
                           @@@@@@@   O      \
                          @@@@@@@@@@     @@@ \
                          @@@@@@@@@@@@ o @@@@|
                          @@@@@@@@@@@@    @@  \		New Moon +      
                             @@@@@@@@ @@@@    |		6 18:38:41.00
                           .  @@   . @@@@@@@  |		First Quarter - 
                               @@@   @@@@@@@  |		0 14:32:22.00
                             . @@@@   @@@@  o /
                                @@   .       |
                            O    .     o   . /
                               .    .       /
                           .      .   .-. /'
                                     `-' /
                         o    O   .   .-'
                              .    .-'
                        .      .--'
                        ------'
% 
% 
% cat phoon.map

[.BIN]PHOON.                                                    24-FEB-1988 10:30        VAX-11 Linker V04-00             Page    1

                                             +------------------------+
                                             ! Object Module Synopsis !
                                             +------------------------+

Module Name     Ident              Bytes      File                                Creation Date      Creator
-----------     -----              -----      -----                               -------------      -------
PHOON           01                   2002 DISK$USER1:[JEF.LIB]PHOON.;1         24-Feb-1988 10:30  VAX FORTRAN V4.6-244
PUTMOON         01                   1589 DISK$USER1:[JEF.LIB]PHOON.;1         24-Feb-1988 10:30  VAX FORTRAN V4.6-244
PUTSECONDS      01                    506 DISK$USER1:[JEF.LIB]PHOON.;1         24-Feb-1988 10:30  VAX FORTRAN V4.6-244
RND             01                    968 DISK$USER1:[JEF.LIB]RNDLB.;1         24-Feb-1988 10:28  VAX FORTRAN V4.6-244
RNDINI          01                   1081 DISK$USER1:[JEF.LIB]RNDLB.;1         24-Feb-1988 10:28  VAX FORTRAN V4.6-244
RNDSEQ          01                     26 DISK$USER1:[JEF.LIB]RNDLB.;1         24-Feb-1988 10:28  VAX FORTRAN V4.6-244
DTARRAY         01                    809 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTSECS          01                     78 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTSKIP          01                     61 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTSTRING        01                    591 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTSUB           01                    281 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTTIME          01                    278 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTTSECS         01                     71 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTUNSECS        01                    106 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTVERIFY        01                    325 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTYEAR          01                    214 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTCTOI          01                    134 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTJUL           01                    424 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTLEAP          01                    124 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTMTOI          01                    717 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTCMP           01                    116 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTDIV           01                     84 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
DTMMATCH        01                    228 RTSGVX$DRC0:[MISC.LIB]DTLB.;1         2-Jan-1987 02:00  VAX FORTRAN V4.4-177
APPCHR          01                    104 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
APPSTR          01                    143 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
CANT            01                    102 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
ST1LB           0                    1029 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-JAN-1987 19:48  VAX/VMS Macro V04-00
CTOI            01                    197 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
ENDST           01                   7245 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
ERROR           01                     90 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
GDATE           01                    252 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:51  VAX FORTRAN V4.4-177
GETARG          01                   1627 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
GETLIN          01                   7662 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1      24-Mar-1987 17:16  VAX FORTRAN V4.6-244
GETNOW          01                    110 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
GTIME           01                    171 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:51  VAX FORTRAN V4.4-177
INITST          01                   8988 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
ITOC            01                    113 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
ITOCZF          01                    202 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
MAKARG          01                   2529 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
OPEN            01                    335 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:47  VAX FORTRAN V4.4-177
PRITS           01                    473 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:38  VAX FORTRAN V4.4-177
PUTCH           01                   7320 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1      24-Mar-1987 17:16  VAX FORTRAN V4.6-244
PUTLIN          01                   7305 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1      24-Mar-1987 17:16  VAX FORTRAN V4.6-244
PUTSPACES       01                     53 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
RGETCH          01                    118 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1      24-Mar-1987 17:16  VAX FORTRAN V4.6-244
RPUTCH          01                    105 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1      24-Mar-1987 17:16  VAX FORTRAN V4.6-244
SETABORTSTATUS  01                     46 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
SKIPBL          01                     69 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
IO1LB           0                    1929 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-JAN-1987 19:22  VAX/VMS Macro V04-00

[.BIN]PHOON.                                                    24-FEB-1988 10:30        VAX-11 Linker V04-00             Page    2


Module Name     Ident              Bytes      File                                Creation Date      Creator
-----------     -----              -----      -----                               -------------      -------
TYPE            01                     78 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
T_CRACK         01                    331 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
T_PUTLINE       01                   8022 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1      24-Mar-1987 17:16  VAX FORTRAN V4.6-244
ASSIGN          01                   7346 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:37  VAX FORTRAN V4.4-177
CLOSE           01                   7256 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:37  VAX FORTRAN V4.4-177
ENBINT          01                    790 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
EXITH           01                    129 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
GETMSG          01                    991 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
GITOC           01                    212 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
INTSRV          01                   3024 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
KILL            01                    116 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:47  VAX FORTRAN V4.4-177
LOOKFORPATH     01                   1421 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:47  VAX FORTRAN V4.4-177
PRIDFT          01                   1029 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:38  VAX FORTRAN V4.4-177
PRIFTF          01                    554 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:38  VAX FORTRAN V4.4-177
RTOC            01                    607 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
STAKE           01                    211 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
TERMIN          01                     62 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
TRNLOG          01                    519 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:47  VAX FORTRAN V4.4-177
TRUNCATE_IFDSKMT               
                01                   7195 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:37  VAX FORTRAN V4.4-177
T_OPEN          01                   8078 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:37  VAX FORTRAN V4.4-177
VMSGETMSG       01                    380 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
ADDSET          01                    110 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
ARGGEN          01                    249 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:47  VAX FORTRAN V4.4-177
CTOC            01                    142 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
DSCBLD          01                    106 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:47  VAX FORTRAN V4.4-177
ENVGET          01                    938 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:11  VAX FORTRAN V4.4-177
FNTOPN          01                    384 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
GETDCL          01                    109 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
GETPNM          01                    139 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:41  VAX FORTRAN V4.4-177
GETWRD          01                    159 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:15  VAX FORTRAN V4.4-177
HTOI            01                    169 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:47  VAX FORTRAN V4.4-177
IOPEN           01                   7251 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:37  VAX FORTRAN V4.4-177
MKLOCL          01                    926 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
MKPATH          01                    512 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
NXTLUN          01                   7189 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:37  VAX FORTRAN V4.4-177
RESDEF          01                   1268 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
STR_HOST        01                    457 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
TRAN1           01                    959 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
TRMOUT          01                     70 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
T_STRIPDEV      01                    770 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
VMSERROUT       01                    591 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
CVT_DTOP        01                   1144 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
DIROUT          01                    488 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
EXPLOG          01                    763 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
EXPPTH          01                    178 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
FGENR8          01                    390 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
GENDIR          01                    362 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
GTDPTH          01                    661 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:53  VAX FORTRAN V4.4-177
GTFTOK          01                    155 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
HOSTNM          01                    137 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:41  VAX FORTRAN V4.4-177
PARSEF          01                    522 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177

[.BIN]PHOON.                                                    24-FEB-1988 10:30        VAX-11 Linker V04-00             Page    3


Module Name     Ident              Bytes      File                                Creation Date      Creator
-----------     -----              -----      -----                               -------------      -------
RES_TILDE       01                    590 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
DIRFIL          01                   2283 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:42  VAX FORTRAN V4.4-177
GHOME           01                    220 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:21  VAX FORTRAN V4.4-177
GTDFLT          01                    545 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:53  VAX FORTRAN V4.4-177
GUSERINFO       01                    230 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177
T_CLOUAF        01                     55 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177
T_GUSERINFO     01                    779 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177
T_OPNUAF        01                    409 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177
ADRFIL          01                     90 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177
CRELOG          01                    179 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
DEFDIR          01                    113 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:53  VAX FORTRAN V4.4-177
GLNAME          01                    185 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       2-Mar-1987 01:01  VAX FORTRAN V4.4-177
GUAFHMDIR       01                    236 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177
GUAFRNAME       01                    216 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177
GUAFUIC         01                    179 RTSGVX$DRC0:[USR.LIB]LIBRARY.;1       1-Jan-1987 19:52  VAX FORTRAN V4.4-177

DISK$USER1:[JEF.BIN]PHOON.;1                                    24-FEB-1988 10:30        VAX-11 Linker V04-00             Page    4

                                                 +----------------+
                                                 ! Image Synopsis !
                                                 +----------------+

Virtual memory allocated:                         00000200 0000EDFF 0000EC00 (60416. bytes, 118. pages)
Stack size:                                             20. pages
Image header virtual block limits:                       1.        1. (    1. block)
Image binary virtual block limits:                       2.       95. (   94. blocks)
Image name and identification:                    PHOON 01
Number of files:                                         9.
Number of modules:                                     122.
Number of program sections:                             16.
Number of global symbols:                              953.
Number of image sections:                               14.
User transfer address:                            00009E00
Debugger transfer address:                        7FFEDF68
Number of code references to shareable images:          22.
Image type:                                       EXECUTABLE.
Map format:                                       BRIEF in file DISK$USER1:[JEF]PHOON.MAP;2
Estimated map length:                             37. blocks
                                              +---------------------+
                                              ! Link Run Statistics !
                                              +---------------------+

Performance Indicators                            Page Faults	CPU Time	Elapsed Time
----------------------                            -----------	--------	------------
    Command processing:                                   137	00:00:00.68	00:00:02.36
    Pass 1:                                               199	00:00:05.25	00:00:18.58
    Allocation/Relocation:                                 18	00:00:00.17	00:00:00.65
    Pass 2:                                               146	00:00:03.78	00:00:25.53
    Map data after object module synopsis:                  0	00:00:00.00	00:00:00.00
    Symbol table output:                                    0	00:00:00.01	00:00:00.18
Total run values:                                         500	00:00:09.89	00:00:47.30

Using a working set limited to 1434 pages and 674 pages of data storage (excluding image)

Total number object records read (both passes):   2644
    of which 1264 were in libraries and 344 were DEBUG data records containing 9134 bytes
8201 bytes of DEBUG data were written,starting at VBN 96 with 17 blocks allocated

Number of modules extracted explicitly             = 0
    with 116 extracted to resolve undefined symbols

123 library searches were for symbols not in the library searched

A total of 0 global symbol table records was written

LINK/MAP/BRIEF/EXECUTABLE=[.BIN]PHOON. PHOON.TMP/OPTIONS

chris@metavax.UUCP ( PSA) (02/26/88)

In article <2323@geac.UUCP> daveb@geac.UUCP (David Collier-Brown) writes:
 
>In article <2984@metavax.UUCP> chris@metavax.UUCP (Chris Collins) writes:
>>	BTW Unix is THE system, for programmers or otherwise, it does
>>have one obvious drawback: it assumes the user is competent.  The idiocy
>>you speak of is not with system!  A lobotomy in your case is not necessary.

I did not make the above statement, only Mike (sorry, can't remember full
name did.  My statement was, "If Unix is the system for programmers. . .".

Secondly, I suppose if I had known the history of the Unix linker, then
I would know that it was a cheap and dirty job.  However, since I have 
been working on non-Unix systems and am migrating to doing work on
Unix in addition to the other systems, I hope to find out that Unix is
a good system.  

Ok, so now I have a new question: Unix has been around a few years, 
I would hope that those who are developing new versions of Unix know 
something of its history.  Therefore, they know that the linker is 
"cheap and dirty", and does not contain functionality clearly evident
in linkers on other systems, so where is the non-"cheap and dirty" 
linker?  

Is there another way to do what these non-Unix linkers do?  Just to
clarify, here's exactly what I want to be able to do:  I have libraries
with multiple subprograms which are related in functionality.  I want
to be able to compile each of these libraries all at once, and then 
when linking an executable extract only the individual subprograms
the executable requires.  I now do this on VM/CMS, VAX/VMS, and MVS/TSO.
Others at my organization claim this can be done on Unisys 1100 machines.
Other posters on this group have stated this works on RSTS and PDP-11's.

    ------ 
   /MM/\MM\          META SYSTEMS, LTD.
  /MM/  \MM\         315 E. Eisenhower
 /MM/ /\ \MM\            Suite 200
 ===  ==  ===       Ann Arbor, MI  48108
 \SS\ \/ /SS/
  \SS\  /SS/        Chris Collins, Senior Programmer
   \SS\/SS/
    ------

ok@quintus.UUCP (Richard A. O'Keefe) (02/26/88)

In article <2323@geac.UUCP>, daveb@geac.UUCP (David Collier-Brown) writes:
>    Both Mike (politely) and Chris (substantially less so) miss the
> point that the Unix linker was a conscious cheap-and-dirty.  The Multics
> system avoided the whole IDEA of static linkers[1], and most if not
> all commercial systems not derived from Unix have better linkers.
> Good Lord, the IBM /360 had a better linker than Unix! (And I
> wouldn't recommend the /3sickly and its linker to my worst enemy).  
> 
I suggest that you take a look at some of the limits of the /360 linker
(e.g. number of entry points per load module).  If you want overlays,
it may well be just what you want.  (The BSD ld(1) is definitely not
state-of-the-art with respect to overlays.  Thank goodness.)

The problem is not the UNIX **linker**.  ld(1) is perfectly capable of
pulling out just the pieces it needs *IF IT IS GIVEN THE RIGHT KIND OF
FILE*.  The problem is the UNIX **compilers**, which don't generate
that sort of file.  There is no reason in principle why the Fortran
compiler, for argument's sake, couldn't generate a '.a' file instead
of a '.o' file.  In fact you can hack that with a shell script:

	#!/bin/sh
	#   NAME:  fca
	#   SYNOPSIS:  fca x.f y.f ....
	#   DESCRIPTION: much the same as f77 -c x.f y.f ...
	#   except that it generates .a files rather than .o files
	#   BUGS: this thing does NO error checking at all!
	#
	Directory=tmp$$
	mkdir $Directory
	cd $Directory
	for File in $*
	    do
		(cd .. ; cat $File) | fsplit
		f77 -c *.f
		Archive=../`basename $File .f`.a
		if -f $Archive 
		    then
			rm $Archive
		    fi
		ar q $Archive *.o
		rm *.o
		ranlib $Archive
	    done
	cd ..
	rm -r $Directory
	exit

What's the problem with doing this to C?  Well, what do you do with
static variables and functions?  (If you can solve this, you can solve
the "shared literals" problem.)  The problem is that if a C source
file is split into pieces (separately loadable segments), the static
variables and functions must be visible to other pieces *from the
same source file*.  So you need THREE levels of names:

    --	names which are strictly local to a single segment (e.g. labels,
	static variables inside functions)

    --	names which are visible within a cluster of segments, but
	not outside that cluster (e.g. shared literals, static
	variables and functions at file level)

    --	names which are visible between clusters.

ld(1) only provides two levels of names.  The missing level could be
simulated by taking a timestamp and the cpuid and using them as a
prefix.  For example,
	static int fred;
might turn into
	M.1200005b22254953.fred
{that's what
	/* do this once per source file */
	sprintf(prefix, "M.%8lx%8lx.", gethostid(), time((long*)0));
	/* do this once per file-level static symbol */
	printf("%s%s\n", prefix, "fred");
 just printed on my terminal.
}
This is not entirely satisfactory, and requires a loader without any
stupid restrictions on the lengths of names (NOT one of the /360's
features...), but combining this with the fca script above shows that
there is no reason why a UNIX compiler could not provide the required
feature without requiring any change to the loader.  Of course, the
debuggers might give you some trouble too...

How about someone providing this as an option in GNU CC?

I know that some other loaders also support only two levels of names.
It wouldn't surprise me if the VMS loader supported three.  But since
most old loaders were developed with Fortran and such in mind, and since
Fortran only needs two levels of names, I'd be surprised if many of them
had the three levels that C needs.

We could profitably turn this into a survey of what the linker
requirements of various languages are:  could an ADA compiler easily
use the UNIX / VMS / MVS / PR1MOS linker?

ok@quintus.UUCP (Richard A. O'Keefe) (02/27/88)

In article <5303@well.UUCP>, pokey@well.UUCP (Jef Poskanzer) writes:
> This discussion is getting fairly tedious, but I guess it's worth one
> more posting, since after all, I'm Right.
> 
> Appended you will find a transcript showing the VAX/VMS linker doing
> exactly what I claimed it does.  I'm using K&P's Software Tools, and
					     ^^^^^^^^^^^^^^^^^^^^
> $ fortran rtsgvx$dra0:[tmp]t174358.f-
    ^^^^^^^
> /obj=rtsgvx$dra0:[tmp]t174395.o/nolist
> rm lib/rndlb

Ah **HAH**!  

I have already posted a message showing how you *CAN* do this in UNIX.
If only he'd said he was talking about Fortran in the first place; several
of the replies explained why it is hard to do this >>for C<<.

Note that I am canny enough not to claim that the VMS C compiler (remember,
it isn't really a linker problem) can't do this too.  If Jef Poskanzer
would care to demonstrate that it can, I'll applaud.

> Moral of the story: just because you can't figure out how to do something
> doesn't mean other people can't.

The way I see it, the moral of the story is that if you don't tell
people what you're trying to do, it's not *their* fault if they assume
you are talking about something else.

ok@quintus.UUCP (Richard A. O'Keefe) (02/28/88)

In article <34588UH2@PSUVM>, UH2@PSUVM.BITNET (Lee Sailer) writes:
> SAS is a million lines of source, and is written in C, though I believe
> it is a traslation from the original PL/1.  They must have some extra
> tools they use--are they homebrew or commercial?

The story I heard is that SAS was originally written in /370 assembly
code.  In 1979, if you asked them "when can we get it for other machines"
their joke was "wait 5 years, and we'll send you a /370 chip with the
tape."  I believe that the rewrite into PL/I enabled the VAX/VMS and
PR1ME/PRIMOS ports, and that the rewrite into C was motivated by the
fact that PL/I isn't all that common on micros and workstations...

SAS is to VM/CMS what AWK is to UNIX, only more so.

franka@mmintl.UUCP (Frank Adams) (03/02/88)

In article <697@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
|We could profitably turn this into a survey of what the linker
|requirements of various languages are:  could an ADA compiler easily
|use the UNIX / VMS / MVS / PR1MOS linker?

In a word, no.  A linker for Ada must check for matching of user-defined
types in different modules.
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

ok@quintus.UUCP (Richard A. O'Keefe) (03/05/88)

In article <2745@mmintl.UUCP>, franka@mmintl.UUCP (Frank Adams) writes:
a In article <697@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
a o We could profitably turn this into a survey of what the linker
a o requirements of various languages are:  could an ADA compiler easily
a o use the UNIX / VMS / MVS / PR1MOS linker?
a In a word, no.  A linker for Ada must check for matching of user-defined
a types in different modules.

In two words, not quite.  There are two things:  planning a link (which
involves working out where to find things and checking that the operation
requested makes sense) and *doing* the link.  Is there any reason why an
ADA compiler could not generate two files: a description file and an
object file, and an ADA linker could not use the information in the
description files to validate and plan the link, and then use the
UNIX / VMS / MVS / PR1MOS linker to *do* the link?  If an ADA program is
to include foreign code (ADA-FORTRAN is a particularly interesting case)
mustn't something like this be done?  Simula has similar link validation
requirements, but Simula compilers normally use the system-supplied linker.

I'm not claiming that this is the best way to do it.
I'm just trying to draw a distinction between finishing off a compilation
and linking.  Maybe there isn't any such distinction if you look hard
enough.  The Burroughs BINDER certainly managed to check interfaces as it
bound together COBOL, ALGOL, and FORTRAN.  Is the fact that the UNIX
linker doesn't check interfaces its greatest weakness?

jos@cs.vu.nl (Jos Warmer) (03/08/88)

In article <34359UH2@PSUVM> UH2@PSUVM.BITNET (Lee Sailer) writes:
>How does this "smart linker" business tie into the "shared libraries"
>in Unix V.3.  As I understand it, (1) when I need a module, the whole
>library is loaded, but (2) when another program needs a module from
>the library, it shares the core image that is already in memory.
>
>So, for example, at any moment, there is only one copy of all the stdio
>(that's standard input-output in Unix-speak) stuff in memory at any given
>moment, and all programs that need it share.  (This also makes the
>executables smaller and saves disk space and load time.)
>
>                                     Just asking,       Lee

Shared libraries do have the advantage of making the
executables smaller.  There is however also a disadvantage
which we stumbled across last week.

We have a program installed under VMS at a client of us.
The program was tested and worked perfectly well for several months.
Then all of a sudden it started to produce erroneous output,
and we got an alarming telephone call.

What happened ?

The day things went wrong, they had a new version of the VMS
C compiler installed, including of course the (shared) libraries.
The errors in the unchanged working program emerged from an
error in the new libraries.

Moral:

    Replacing shared libraries with new versions could make
    lots of working programs crash.  Because those libraries are
    instantaneously used in almost ALL running programs, one
    error in such a library can be fatal for the complete system.

	Jos Warmer,
	VU Informatica Amsterdam
	jos@cs.vu.nl

wesommer@athena.mit.edu (William Sommerfeld) (03/09/88)

In article <667@kajak.cs.vu.nl> jos@cs.vu.nl (Jos Warmer) writes:
>    Replacing shared libraries with new versions could make
>    lots of working programs crash.  Because those libraries are
>    instantaneously used in almost ALL running programs, one
>    error in such a library can be fatal for the complete system.

A properly designed shared library system should deal gracefully with
version skew.

Ideally, the installation of a new library should be done such that
existing processes can continue to use the old version of the library,
while new processes which start up see the new version.

Also, there should be a facility to allow just one process to run with
a new version of a shared library, to test compatibility with the old
version, although this is less important in a single-user workstation
environment than in a timesharing environment.

All this implies that the interface to the routines is unchanged, and
that only the _implementation_ of the library is changed in the new
version; changing the interface of a library routine will be painful
unless you've had the foresight to include some sort of version
numbering system.

					- Bill

UH2@PSUVM.BITNET (Lee Sailer) (03/10/88)

In article <667@kajak.cs.vu.nl>, jos@cs.vu.nl (Jos Warmer) says:
>
>The day things went wrong, they had a new version of the VMS
>C compiler installed, including of course the (shared) libraries.
>The errors in the unchanged working program emerged from an
>error in the new libraries.
>

Shared library systems should have some mechanism for avoiding this type
of problem.  How about this:

When object files are created, the startup code includes a check of the
version of the library used.  Then, if the library changes, the startup
code sends urgent mail to the person responsible for supporting the code,
such as the local system administrator, the vendors (via email?), and the
user (this is optional).

Another approach would be to keep the old libraries around, and have
the using object file specify a library version number.