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.