[net.unix-wizards] 4.2::SYSV compatability problem

BostonU SysMgr <root%bostonu.csnet@csnet-relay.arpa> (01/29/85)

Apologies in advance if this has been resolved in the past or I am being
dense (although that means several people here got denseness problems):

Under 4.2bsd if, say, you have a foo.h file with a line like:

	int thing ;

and include it in a few .c files everything goes fine. In SYS5
(we are running SYS5.2 on a 3B5) you get 'multiply defined' errors.
Ok, not unexpected. I have in the past just changed such a file to
something like:

#ifdef MAIN
#define EXTERN
#else
#define EXTERN extern
#endif

EXTERN int thing ;

And defined MAIN in only one place (like where main() occurs.)

Problem: Suppose now you are faced with a program with about 40 .h files
and probably hundreds of such indiscretions. WORSE: many many typedefs
making something like 'g/int /s//EXTERN int /' (if I may speak ed in
mixed company) for each C type not enough.

What's a nurd to do? 'Fixing' SYS5 ld certainly comes to mind,
(apparently berkeley already took this course once) any other
suggestions welcome as it will be a few weeks before sources arrive and
I got things to get on with....

Tx in advance.

	-Barry Shein, Boston University

Doug Gwyn (VLD/VMB) <gwyn@Brl-Vld.ARPA> (01/29/85)

UNIX System V Release 2.0 is not supposed to give "multiply defined"
messages for multiple extern object allocations, unless you specifically
ask for them by the -M option to "ld" (or "cc").  Check this, and if
there is still a problem, use "trenter" or mail an MR to the support
organization.

BostonU SysMgr <root%bostonu.csnet@csnet-relay.arpa> (01/29/85)

	Sorry, that was System 5 Release 3.0 on a 3B5.
	Doug Gwyn mentioned that 5 release 2.0 is not
	supposed to give this error unless a -M flag
	is specified. In this manual (which is different
	from release 2.0) there is no -M flag in ld (or cc.)

	Did they fix then break it or do the releases have
	no relation to time? (eg. release 3.0 is later then
	release 2.0 and should have some superset of improvements
	of 1.0->2.0.)

guy@rlgvax.UUCP (Guy Harris) (01/29/85)

Ah yes, the old "multiple extern" problem.

The C language reference says that only one definition of an external
variable (i.e. something without "extern" in front of it) is allowed;
all other declarations must be references using "extern".  This is because
the UNIX linker is one of the few linkers (the only one?) which uses the
FORTRAN common-block model for external declarations, where if the symbol
is defined several times it takes the biggest of the declarations and
uses that.  Most other linkers choke if given more than one declaration.

In practice, since the UNIX linker doesn't choke on multiple declarations
(prior to System V), UNIX code was written to assume it was OK to declare
something more than once.  The System V linker was changed to choke on
this - I guess to "enforce" the same restriction that other linkers have,
in order to detect code that couldn't be moved to other OSes.  The System
V Release 2 linker, on the VAX at least, changed this back (in response
to a chorus of howls from users, I suspect) but provided an option to
support the old S5R1 behavior.  I suspect AT&T may not have put the latest
linker into your 3B; complain to them (or change your code; once that's
done, it makes it more likely that the code will work on other systems
which don't use the common-block model for externals).

And no, Berkeley didn't fix anything.  Bell, arguably, broke something
in S5R1; given that they changed it back in S5R2, they may agree.  (Lots
of things that you might think are "Berkeley vs. S5" or "Berkeley vs. Bell"
aren't.)

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

jhh@ihldt.UUCP (John Haller) (02/03/85)

Try using Mcc rather than cc.  If Mcc doesn't exist, link cc to Mcc,
and do the same for things in /lib.  I suspect that you are running
System V, Release 1, and the third release of that for the 3B5.
The hue and cry complaining about cc being broken in System V
Release 1 came too late for cc to be fixed properly, as it is in
System V, Release 2.  Hence the kludge.

carl@rtech.ARPA (Carl Resnikoff ) (02/06/85)

> 
> Apologies in advance if this has been resolved in the past or I am being
> dense (although that means several people here got denseness problems):
> 
> Under 4.2bsd if, say, you have a foo.h file with a line like:
> 
> 	int thing ;
> 
> and include it in a few .c files everything goes fine. In SYS5
> (we are running SYS5.2 on a 3B5) you get 'multiply defined' errors.
> Ok, not unexpected. I have in the past just changed such a file to
> something like:
> 
> #ifdef MAIN
> #define EXTERN
> #else
> #define EXTERN extern
> #endif
> 
> EXTERN int thing ;
> 
> And defined MAIN in only one place (like where main() occurs.)
> 
> Problem: Suppose now you are faced with a program with about 40 .h files
> and probably hundreds of such indiscretions. WORSE: many many typedefs
> making something like 'g/int /s//EXTERN int /' (if I may speak ed in
> mixed company) for each C type not enough.
> 
> What's a nurd to do? 'Fixing' SYS5 ld certainly comes to mind,
> (apparently berkeley already took this course once) any other
> suggestions welcome as it will be a few weeks before sources arrive and
> I got things to get on with....
> 
> Tx in advance.
> 
> 	-Barry Shein, Boston University


I have great sympathy for you, having once lived in a motel
room in Red Bank, New Jersey while fixing a very large (> 100,000
lines) C program written in BSD C so that SYS V C could load it.
However....

If you have any hope of porting your code to any other environments
(e. g. DEC C on VMS, Whitesmith C), fix your code and not SYS V ld.

DEC (VMS) C loader expects variables to be allocated with "globaldef"
and to be referenced with "globalref", while Whitesmith loader expects
all allocated variables to be initialized (or else no space is
allocated).  Besides, even on BSD, its nice to know where your
variables are really allocated, in case you ever want to tune your
programs to reduce paging, etc.

One way to handle these cases is  to have macros like

#define EXTERN extern /* or globalref or whatever */
#define GLOBAL globaldef /* or nothing */
#define FILL   ={0}     /* this works for structs, int's etc */
			/* you can also make it blank if non needed */

and you can say

int i FILL;
typedef struct {...} foo;
foo Foo1 FILL;
EXTERN int i;

Carl Resnikoff (ucbvax!mtxinu!rtech!carl)

guy@rlgvax.UUCP (Guy Harris) (02/10/85)

> > (Discussion of the fact that some System V versions enforce the
> > "only one definition of an extern" rule)

> I have great sympathy for you, having once lived in a motel
> room in Red Bank, New Jersey while fixing a very large (> 100,000
> lines) C program written in BSD C so that SYS V C could load it.
> 
> Besides, even on BSD, its nice to know where your
> variables are really allocated, in case you ever want to tune your
> programs to reduce paging, etc.

****it, the world is *NOT* divided into BSD and System V - it's not
even divided into BSD and USG!  System V is the *only* UNIX system that
enforced that rule.  V6, PWB/UNIX 1.0, V7, and System III worked the same
way as 4.xBSD did - in fact, 4.xBSD behaved that way because 32V behaved
that way, and 32V behaved that way because V7 behaved that way, and...

So next time you run into an incompatibility between one version of UNIX
and another, don't jump to conclusions as to whose fault it is... System V
Release 2 backed the change out, probably because so many people lived
in motel rooms in Red Bank (count your blessings, it wasn't Secaucus).
Lay the blame/credit for that one squarely at the feet of the USDL.

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

Doug Gwyn (VLD/VMB) <gwyn@Brl-Vld.ARPA> (02/10/85)

But the idea of making extern objects conform to a DEF/REF model
is a good one (forced upon the C implementor on a wide variety of
systems); it's just changing the semantics on UNIX that was not
such a hot idea.  (Although K&R described DEF/REF semantics, few
UNIX programmers paid heed, since UNIX used a COMMON model.)

The draft ANSI C spec requires DEF/REF, but in a small note in an
Appendix the COMMON model is mentioned as a "common extension".
C programmers should start conforming to DEF/REF semantics if they
are not already doing so; this works on UNIX and will continue to
work on other C systems (including perhaps future UNIXes).

stewart@houxf.UUCP (Bill Stewart HO 4K-435 x0705) (02/16/85)

>>>>> System V didn't let you use multiply defined External refs.

Actually, USG (or whoever) very quickly came out with 'Mcc', the
multiple-externs-ok version of cc, because of the level of screaming from the
general community.  I don't know if it got released outside BTL (I assume it
did?), but if you were staying in a motel in Red Bank fixing it you were
probably working here.
-- 
Bill Stewart	ho95c!wcs AT&T Bell Labs, Holmdel NJ
HO 4K-435 x0705   (201-949-0705)
{allegra, ucbvax!ihnp4, decvax!harpo}!houxf!stewart
------
Sorry if the articles I'm replying to re ancient; we lost news for a month.