[comp.unix.questions] Telling csh about multiple, machine-dependent libraries

jc@heart-of-gold (John M Chambers) (11/17/88)

Here's one that someone has gotta have solved already:

We have NFS-mounted filesystems on a lot of different kinds of machines,
and of course there is a problem with trying to execute binary files on
the wrong machine.  It's pretty easy to build the binaries, of course;
I just set up a heirarchy:
	~foo/src	contains generic source.
	~foo/sun2	contains a Makefile and binaries for a Sun2
	~foo/sun3	contains a Makefile and binaries for a Sun3
	~foo/vax	contains a Makefile and binaries for a VAX
	~foo/x286	contains a Makefile and binaries for a 80286/Xenix
	~foo/x386	contains a Makefile and binaries for a 80386/Xenix 
and so on.  Source files are linked from src as necessary.

Now, when I log in, I'd like  to include the right directory in my search
path.  My latest (failed) attempt in cshrc looks like:

| set mtype = bin
| if (`sun2`) set mtype = sun2
| if (`sun3`) set mtype = sun3
| if (`sun4`) set mtype = sun4
| set path=(. ~/{$mtype,sh,csh,awk} /bin /usr/{ucb,etc,local,local/{$mtype,sh},bin,lib,dos,hosts,games,demo,NeWS/{bin,demo}} /etc)

Note that the replicated binary directories are also in /local, as a simple
way of getting public libraries.  Anyhow, as I said, the above code doesn't
work.  While the `sun3` command on this 3/260 returns TRUE (i.e., 0), the
value of $path includes ~/bin, not ~/sun3.  I've tried a few other variants,
includeing such things as
	sun3 && set mtype = sun3
all to no avail.

Does anyone know how to do this right?

For that matter, the above code, if taken to a machine that lacks, e.g., 
a `sun4` command, bombs out and fails to read the rest of .cshrc, so this 
is obviously not a general approach.  In reading the manuals, I haven't 
been able to find any way of answering the question "What the hell sort 
of CPU am I running on, anyway?"  I also don't recall ever reading any 
flame session (oops, I mean in-depth technical discussion) of the topic 
on usenet.  Is there a portable answer to this question?

chris@mimsy.UUCP (Chris Torek) (11/18/88)

[`heart-of-gold' is not in the UUCP maps, and linus claims never to have
heard of the machine, although the news path is linus!heart-of-gold!jc;
what goes on here?]

In article <173@heart-of-gold> jc@heart-of-gold (John M Chambers) writes:
>| set mtype = bin
>| if (`sun2`) set mtype = sun2
>| if (`sun3`) set mtype = sun3
>| if (`sun4`) set mtype = sun4
>| set path=(. ~/{$mtype,sh,csh,awk} /bin /usr/{ucb,etc,local,local/{$mtype,sh},bin,lib,dos,hosts,games,demo,NeWS/{bin,demo}} /etc)

The proper syntax is

	if ( { program } ) ...

The {} pair will substitute for the () pair, so you can write

	if { program } ...

or in this case

	if { sun2 } set mtype = sun2
	if { sun3 } set mtype = sun3
	if { sun4 } set mtype = sun4

>...  I've tried a few other variants, includeing such things as
>	sun3 && set mtype = sun3

This should work.  If you have the `machine' command (and it does
the right thing) you can also use

	switch (`machine`)
	case sun2:
		set mtype = sun2
		breaksw
	case sun3:
		set mtype = sun3
		breaksw
	case sun4:
		set mtype = sun4
		breaksw
	default:
		echo "unknown machine type `machine`"
		breaksw
	endsw

or (much simpler)

	set mtype = `machine`

>For that matter, the above code, if taken to a machine that lacks, e.g., 
>a `sun4` command, bombs out and fails to read the rest of .cshrc, so this 
>is obviously not a general approach.

This is one reason `machine` is preferable if available.  csh does not
have a convenient way to test the existence of a program; but you can
always use a Bourne shell script instead:

	set mtype = `sh .get-machine`

where `.get-machine' reads

	if (set -e; machine) >/dev/null 2>&1; then
		machine
	else
		echo "no \`\`machine'' command; assuming \`\`bin''" 1>&2
		echo bin
	fi
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gandalf@csli.STANFORD.EDU (Juergen Wagner) (11/18/88)

In article <14592@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>...
>This should work.  If you have the `machine' command (and it does
>the right thing) you can also use
>...
>	set mtype = `machine`
>...

On our Sun4, the "arch" command is what your "machine" command is. The point
is, different machine architectures might use different commands. The way I
am finding out what machine type I am on is quite simple (though a bit more
CPU expensive than a short script):

  setenv HOSTTYPE "`/lib/cpp -P < ${HOME}/conf/hosttype`"

where the file ~/conf/hosttype contains something like
    # undef ok
    # ifndef ok
    # if sun
    # undef sun
    #   ifdef sparc
    #   undef sparc
    sparc
    #   else
    sun
    #   endif
    # define ok
    # endif
    # endif
    ...
    # ifndef ok
    unknown
    # endif

This uses the guaranteed feature of cpp to have the predefined symbols "sun",
"sparc", "vax", "hpux", etc. Everything else seemed to be different across
machine architectures.

-- 
Juergen Wagner		   			gandalf@csli.stanford.edu
						 wagner@arisia.xerox.com

gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/18/88)

In article <6490@csli.STANFORD.EDU> wagner@arisia.xerox.com (Juergen Wagner) writes:
>This uses the guaranteed feature of cpp to have the predefined symbols "sun",
>"sparc", "vax", "hpux", etc.

Boy, are you in for a surprise.

matthew@sunpix.UUCP ( Sun NCAA) (11/19/88)

In article <173@heart-of-gold>, jc@heart-of-gold (John M Chambers) writes:
> Here's one that someone has gotta have solved already:
> 
> We have NFS-mounted filesystems on a lot of different kinds of machines,
> and of course there is a problem with trying to execute binary files on
> the wrong machine.  It's pretty easy to build the binaries, of course;
> I just set up a heirarchy:
> 	~foo/src	contains generic source.
> 	~foo/sun2	contains a Makefile and binaries for a Sun2
> 	~foo/sun3	contains a Makefile and binaries for a Sun3
> 	~foo/vax	contains a Makefile and binaries for a VAX
> 	~foo/x286	contains a Makefile and binaries for a 80286/Xenix
> 	~foo/x386	contains a Makefile and binaries for a 80386/Xenix 
> and so on.  Source files are linked from src as necessary.
> 
> Now, when I log in, I'd like  to include the right directory in my search
> path.  My latest (failed) attempt in cshrc looks like:
> 
> | set mtype = bin
> | if (`sun2`) set mtype = sun2
> | if (`sun3`) set mtype = sun3
> | if (`sun4`) set mtype = sun4
> | set path=(. ~/{$mtype,sh,csh,awk} /bin /usr/{ucb,etc,local,local/{$mtype,sh},bin,lib,dos,hosts,games,demo,NeWS/{bin,demo}} /etc)
> 

Close, but not quite right.  We have to do build for not just different
machines, but different OS also. 

What you need to do is use the `arch` command to differenciet(sp?) between
the different machine types. IE:

set mtype = `arch` 

is what you are looking for. We also use a shell script to determine the OS
level also. Here it is:

#! /bin/csh -f
# Prints "os3", "os4", or "os_unknown"
# Set rel_str to the string following "Release" in /vmunix

#/*note: following two line are actually one. broken here due to length > 80 */
set rel_str = `strings /vmunix | grep Release | 
awk '{ for (i=0; i<NF; i++) if ($i == "Release"){ i++; print $i; exit; } }'`

if ($rel_str:r == 3 || $rel_str == Sys4-3.2) then
  echo "os3"
else if ($rel_str:r == 4) then
  echo "os4"
else
  echo "os_unknown"
endif


This way we can create directories for 'sun3-os3', 'sun3-os4', 'sun4-os3',
and 'sun4-os4' with a simple:

set PATH = $PATH ~/`arch`-`os`


Hope this helps.
-- 
Matthew Lee Stier     (919) 469-8300|
Sun Microsystems ---  RTP, NC  27560|          "Wisconsin   Escapee"
uucp: {sun, rti}!sunpix!matthew     |

dtynan@sultra.UUCP (Der Tynan) (11/19/88)

In article <6490@csli.STANFORD.EDU>, gandalf@csli.STANFORD.EDU (Juergen Wagner) writes:
> where the file ~/conf/hosttype contains something like
>     # if sun
>     # undef sun
>     #   ifdef sparc
>     #   undef sparc
>     sparc
>     #   else
	...
> 
> This uses the guaranteed feature of cpp to have the predefined symbols "sun",
> "sparc", "vax", "hpux", etc. Everything else seemed to be different across
> machine architectures.
> 
> Juergen Wagner	   			gandalf@csli.stanford.edu

This may not work either.  At least, not in the general case.  For example,
what's the definition for a 68000?  I've seen both m68000 and m68k used.
Similar things happen with the Intel family.  Also, for example, the MINIX
C compiler balks when it sees;

#ifdef 3b1

For some reason it doesn't like the '3'.  What we need around here, is a
'standard'!
						- Der
-- 
	dtynan@zorba.Tynan.COM  (Dermot Tynan @ Tynan Computers)
	{apple,mips,pyramid,uunet}!Tynan.COM!dtynan

 ---  If the Law is for the People, then why do we need Lawyers? ---

ok@quintus.uucp (Richard A. O'Keefe) (11/19/88)

>In article <173@heart-of-gold>, jc@heart-of-gold (John M Chambers) writes:
>> Now, when I log in, I'd like  to include the right directory in my search
>> path.  My latest (failed) attempt in cshrc looks like:
>> 
>> | set mtype = bin
>> | if (`sun2`) set mtype = sun2
>> | if (`sun3`) set mtype = sun3
>> | if (`sun4`) set mtype = sun4
>> | set path=(. ~/{$mtype,sh,csh,awk} /bin /usr/{ucb,etc,local,local/{$mtype,sh},bin,lib,dos,hosts,games,demo,NeWS/{bin,demo}} /etc)

Here's a script of mine that may help.  I would welcome any corrections
or additions.

#!/bin/sh
cat >machine <<'EOF'
#!/bin/sh
IFS=" 	"
#   Script : machine
#   Author : Richard A. O'Keefe
#   Purpose: Write the machine type on the standard output stream.
#
#   Copyright (C) 1988, Quintus Computer Systems, Inc.
#   This may be used freely provided this copyright notice is preserved.
#
#   There is a problem here.  I originally wrote
#	if [ -x /bin/FOO ] && /bin/FOO; then echo FOO
#   but the -x option does not exist on all systems.

if   [ -r /bin/sun     ] && /bin/sun     ; then
     # /bin/arch is not present in all versions of SunOS; local hack.
     if [ -r /bin/arch ] && /bin/arch >/dev/null ; then
	/bin/arch
    else
	echo sun2
    fi
elif [ -r /bin/apollo  ] && /bin/apollo  ; then
    # No test for DN10000 yet, only 680x0 models.
    echo apollo
elif [ -r /bin/s5k30  ] && /bin/s5k30    ; then
    # Recognise Unisys 5000/X machines with "s5k*)"
    # Unisys 5000/30
    echo s5k30
elif [ -r /bin/s5k50  ] && /bin/s5k50    ; then
    # Unisys 5000/50
    echo s5k50
elif [ -r /bin/s5k80  ] && /bin/s5k80    ; then
    # Unisys 5000/80
    echo s5k80
elif [ -r /bin/s5k85  ] && /bin/s5k85    ; then
    # Unisys 5000/30
    echo s5k85
elif [ -r /bin/s5k90  ] && /bin/s5k90    ; then
    # Unisys 5000/90
    echo s5k90
elif [ -r /bin/s5k95  ] && /bin/s5k95    ; then
    # Unisys 5000/95
    echo s5k95
elif [ -r /bin/s7k40  ] && /bin/s7k40    ; then
    # Recognise Unisys 7000/X machines with "s7k*)"
    # Recognise both groups with "s?k*)"
    # Unisys 7000/40 or 7000/30
    echo s7k40
elif [ -r /bin/s7k50  ] && /bin/s7k50    ; then
    # Unisys 7000/50
    echo s7k50
elif [ -r /bin/s7k51  ] && /bin/s7k51    ; then
    # Unisys 7000/51
    echo s7k51
elif [ -r /bin/s7k52  ] && /bin/s7k52    ; then
    # Unisys 7000/52
    echo s7k52
elif [ -r /bin/m68k    ] && /bin/m68k    ; then
    # "other" Motorola 680x0, probably System V/68
    echo m68k
elif [ -r /bin/vax     ] && /bin/vax     ; then
    echo vax
elif [ -r /bin/i386    ] && /bin/i386    ; then
    # This covers Sequent and Intel machines at least
    echo i386
elif [ -r /bin/i286    ] && /bin/i286    ; then
    echo i286
elif [ -r /bin/ns32000 ] && /bin/ns32000 ; then
    echo ns32000
elif [ -r /bin/u3b15   ] && /bin/u3b15   ; then
    # Recognise 3B machines in general with "3b*)"
    echo u3b15
elif [ -r /bin/u3b10   ] && /bin/u3b10   ; then
    echo u3b10
elif [ -r /bin/u3b5    ] && /bin/u3b5    ; then
    echo u3b5
elif [ -r /bin/u3b2    ] && /bin/u3b2    ; then
    echo u3b2
elif [ -r /bin/u3b     ] && /bin/u3b     ; then
    # Actually, 3B/20
    echo u3b
elif [ -r /bin/u370    ] && /bin/u370    ; then
    echo u370
elif [ -r /bin/pdp11   ] && /bin/pdp11   ; then
    echo pdp11
else
    echo unknown
    exit 1
fi
exit 0
EOF
chmod a=rx machine
exit 0

gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/20/88)

In article <2662@sultra.UUCP> dtynan@sultra.UUCP (Der Tynan) writes:
>... the MINIX C compiler balks when it sees;
>#ifdef 3b1
>For some reason it doesn't like the '3'.  What we need around here, is a
>'standard'!

"3b1" is not a valid identifier since it doesn't start with a letter or
underscore.

We've been working on the standard.  It won't permit predefined
identifiers unless they start with an underscore or two.

jc@minya.UUCP (John Chambers) (11/25/88)

> This uses the guaranteed feature of cpp to have the predefined symbols "sun",
> "sparc", "vax", "hpux", etc. Everything else seemed to be different across
> machine architectures.

Which reminds me:  Is it written down anywhere how one might go about finding
out what symbols are pre-defined by a C pre-processor?  I know that "unix" is
generally pre-defined on Unix systems, and there's usually some symbol that
identifies the cpu and/or model, but how do I find out what it is?  I've read
lots of manuals, and never seen it mentioned.  I've generally attacked ccp 
with a "strings /lib/cpp" and looked for the table, but this is probably not 
the approved method.

On this machine, the result includes the following:
	define
	undef
	include
	else
	endif
	ifdef
	ifndef
	if
	line
	class
	ident
	unix
	m68k
	__LINE__
	__FILE__
Some of these are obvious.  The "m68k" clearly means that this is a Motorola
68000. In fact, it's a 68010, though there's no way you can tell that from
the above.  I wonder what "class" and "ident" do?  The cpp(1) page doesn't
mention them.  There appears to be nothing telling the make/model of the
machine or compiler.

What does your cpp pre-define?

-- 
John Chambers <{adelie,ima,maynard,mit-eddie}!minya!{jc,root}> (617/484-6393)

[Any errors in the above are due to failures in the logic of the keyboard,
not in the fingers that did the typing.]

gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/27/88)

In article <142@minya.UUCP> jc@minya.UUCP (John Chambers) writes:
> I wonder what "class" and "ident" do?  The cpp(1) page doesn't mention them.

#class indicates that the "classes preprocessor" is to be run.
This support for "C with classes" is now obsolete; it has been
replaced by C++.

#ident "string" causes the string to be placed in a special ident
record in the object module, so that it can be found by "what"
without wasting space in the actual load image.  This is an AT&T
innovation.

Neither #class nor #ident, nor system-dependent predefined macros
not starting with at least one underscore, are allowed in a C
implementation that conforms to the proposed ANSI standard.

#elif (not shown in your list) is required.

friedl@vsi.COM (Stephen J. Friedl) (11/29/88)

In article <142@minya.UUCP>, jc@minya.UUCP (John Chambers) writes:
> Some of these [cpp defines] are obvious.
> I wonder what "class" and "ident" do?

These are products of the AT&T compiler.  #ident is used to put
SCCSID-style info into an object file, and it takes a string
literal. #class was used with `C with Classes', the predecessor
to C++, and it may call up some kind of preprocessor.

     Steve

-- 
Steve Friedl    V-Systems, Inc.  +1 714 545 6442    3B2-kind-of-guy
friedl@vsi.com     {backbones}!vsi.com!friedl    attmail!vsi!friedl
------------Nancy Reagan on climaxes: "Just say moan!"-------------
:wq!

guy@auspex.UUCP (Guy Harris) (11/29/88)

>I wonder what "class" and "ident" do?  The cpp(1) page doesn't mention
>them.

"class" is left over from an ancestor of C++, I believe; that language
was named "C with classes" or something like that. 

"ident" is an S5R3-ism; it takes a character string as an argument, and
gets passed through to the compiler, which tells the assembler to stick
the string into a special "SCCS IDs" section of the object file.  That
way, SCCS IDs are in the object file (and in the source file, by virtue
of the "#ident" line), but not in the address space of a process that
runs an executable.  There's a command that will remove the "SCCS IDs"
section, in case you don't want to spend disk blocks on it.

Some systems implement it but don't pass it through to the compiler;
this is done for S5R3 compatibility, so that you don't have to rip the
"#ident" lines out.  4.3BSD and SunOS 4.0 do this. 

merlyn@intelob.biin.com (Randal L. Schwartz @ Stonehenge) (11/29/88)

In article <142@minya.UUCP>, jc@minya (John Chambers) writes:
| Which reminds me:  Is it written down anywhere how one might go about finding
| out what symbols are pre-defined by a C pre-processor?  I know that "unix" is
| generally pre-defined on Unix systems, and there's usually some symbol that
| identifies the cpu and/or model, but how do I find out what it is?  I've read
| lots of manuals, and never seen it mentioned.

On one rainy afternoon (lots of those here in Oregon :-), I hacked out the
following:

strings -2 /lib/cpp |
grep '^[_A-Za-z][_A-Za-z0-9]*$' |
sort -u |
awk '
	{
		print "#ifdef " $0
		print "__" $0 "__ is defined"
		print "#endif"
	}
' |
/lib/cpp |
sed -n 's/^__\(.*\)__ is defined$/\1/p'

Looking at it now, I can see a couple of bugs (like if both X and
__X__ are predefined, you lose), but you get the idea.

Running on this Ultrix thing (I think)... I get:
  __FILE__
  __LINE__
  bsd4_2
  ultrix
  unix
  vax

Yup.  Ultrix is defined.
-- 
Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095
on contract to BiiN Technical Information Services (for now :-),
in a former Intel building in Hillsboro, Oregon, USA.
<merlyn@intelob.biin.com> or ...!tektronix!inteloa[!intelob]!merlyn
SOME MAILERS REQUIRE <merlyn@intelob.intel.com> GRRRRR!
Standard disclaimer: I *am* my employer!

friedl@vsi.COM (Stephen J. Friedl) (11/29/88)

In article <530@auspex.UUCP>, guy@auspex.UUCP (Guy Harris) writes:
> 
> "ident" is an S5R3-ism;

SVR2 compilers on the 3B2 have had #ident since (at least) pcc2.

< It takes a character string as an argument, and
< gets passed through to the compiler, which tells the assembler to stick
< the string into a special "SCCS IDs" section of the object file.

It's the ".comment" section (as opposed to .text, .data, or .bss).

< That way, SCCS IDs are in the object file (and in the source file, by virtue
< of the "#ident" line), but not in the address space of a process that
< runs an executable.  There's a command that will remove the "SCCS IDs"
< section, in case you don't want to spend disk blocks on it.

The command that diddles with this is  `mcs' (manipulate comment section).

< Some systems implement it but don't pass it through to the compiler;
< this is done for S5R3 compatibility, so that you don't have to rip the
< "#ident" lines out.  4.3BSD and SunOS 4.0 do this. 

This is mighty nice of them -- I like #ident.

     Steve

-- 
Steve Friedl    V-Systems, Inc.  +1 714 545 6442    3B2-kind-of-guy
friedl@vsi.com     {backbones}!vsi.com!friedl    attmail!vsi!friedl
------------Nancy Reagan on climaxes: "Just say moan!"-------------
:wq!