"Numerical Recipes in C" is nonportable code

6 views
Skip to first unread message

Rob Carriere

unread,
Aug 27, 1988, 8:56:09 PM8/27/88
to
In article <13...@mimsy.UUCP> ch...@mimsy.UUCP (Chris Torek) writes:
> [ still on the b = malloc( foo ); bb = b - 1; code in NumRecipes ]
>Such an implementation will ABORT ON THE COMPUTATION `b - 1',
>possibly (indeed, preferably) at compile time. And it is legal!

So the standard says, they tell me. It is also one the more flagrant
violations of the Principle of Least Astonishment I've seen in a
while. In fact, while we're at it, it would seem to violate the idea
that you give the programmer all the rope she asks for, because she
just might be needing it to pull herself out of a bog. Gentlemen
system programmers, surely you too have algorithms that are more
accurately expressed with arrays from other than base zero?

T. William Wells

unread,
Aug 29, 1988, 2:19:02 AM8/29/88
to
In article <5...@accelerator.eng.ohio-state.edu> r...@kaa.eng.ohio-state.edu (Rob Carriere) writes:

: In article <13...@mimsy.UUCP> ch...@mimsy.UUCP (Chris Torek) writes:
: > [ still on the b = malloc( foo ); bb = b - 1; code in NumRecipes ]
: >Such an implementation will ABORT ON THE COMPUTATION `b - 1',
: >possibly (indeed, preferably) at compile time. And it is legal!
:
: So the standard says, they tell me. It is also one the more flagrant
: violations of the Principle of Least Astonishment I've seen in a
: while.

Actually, on a segmented architecture I might be astonished if it
*didn't* bomb. The principle is rather subjective I'm afraid.

: In fact, while we're at it, it would seem to violate the idea


: that you give the programmer all the rope she asks for, because she
: just might be needing it to pull herself out of a bog.

Note that the standard does *not* say that you can't do this, it
just says that it is nonportable. So, unless this bog is a
portable bog, she (Ugh. I prefer s/h/it for a neutered pronoun :-)
won't need a portable rope!

: Gentlemen


: system programmers, surely you too have algorithms that are more
: accurately expressed with arrays from other than base zero?

Well, actually, no. One of the characteristics of being *very*
experienced with a language is that you tend to think of
solutions in terms of what that language most easily supplies.

Hmmmm. Now that I think about it, I do seem to recall some Shell
sort where a zero base made the code more complex.

However, since there *is* a portable way to do this (if you don't
mind the syntax), I'll show it.

func()
{
int foo_array[SIZE][SIZE];
#define foo(n,m) (foo_array[(n)-1][(m)-1])
...
}

Ugly, but it works. And it can be used to make the NR programs
portable.

---
Bill
novavax!proxftl!bill

Henry Spencer

unread,
Aug 29, 1988, 12:50:33 PM8/29/88
to
>>Such an implementation will ABORT ON THE COMPUTATION `b - 1',
>>possibly (indeed, preferably) at compile time. And it is legal!
>
>So the standard says, they tell me. It is also one the more flagrant
>violations of the Principle of Least Astonishment I've seen in a
>while. In fact, while we're at it, it would seem to violate the idea
>that you give the programmer all the rope she asks for, because she
>just might be needing it to pull herself out of a bog. Gentlemen
>system programmers, surely you too have algorithms that are more
>accurately expressed with arrays from other than base zero?

Yes, certainly. However, if one wants such code to be portable, one must
be careful how one computes addresses into such arrays. The only fully
portable way to compute a[b] when you want "a" to start at subscript "s"
is a[b-s]. (a-s)[b] certainly is appealing, since it permits doing the
subtraction once rather than every time, but it is *NOT PORTABLE*. Thanks
primarily (but not exclusively) to Intel, it is not safe to back a pointer
up past the beginning of an array and then advance it again. C has never
guaranteed this to work; indeed, there have always been explicit warnings
that once the pointer goes outside the array, all bets are off. X3J11 has
legitimized pointers just past the end of an array, since this is very
common and is cheap to do, even on difficult machines, but the beginning
of an array remains an absolute barrier to portable pointers. This is
simply a fact of life in the portability game.
--
Intel CPUs are not defective, | Henry Spencer at U of Toronto Zoology
they just act that way. | uunet!attcan!utzoo!henry he...@zoo.toronto.edu

Walter Bright

unread,
Aug 29, 1988, 2:11:50 PM8/29/88
to
<In article <13...@mimsy.UUCP< ch...@mimsy.UUCP (Chris Torek) writes:
<< [ still on the b = malloc( foo ); bb = b - 1; code in NumRecipes ]
<<Such an implementation will ABORT ON THE COMPUTATION `b - 1',
<<possibly (indeed, preferably) at compile time. And it is legal!
<So the standard says, they tell me. It is also one the more flagrant
<violations of the Principle of Least Astonishment I've seen in a
<while.

On a segmented architecture, like 8086's, malloc can and does return
a value that is a pointer to the beginning of a segment. That is, there
is a 16 bit selector and a 16 bit offset, the offset portion is 0 or a
very small number. Thus, subtracting a value from the pointer could result
in a segment wrap. Trouble occurs when you do things like:
array = malloc(MAX * sizeof(array[0]));
for (p = &array[MAX-1]; p >= &array[0]; p--)
...
The >= will fail, because the last p-- will cause an underflow and now
p is greater than &array[MAX]! I've encountered this many times in
porting code from Unix to PCs. The correct way to write the loop is:
for (p = &array[MAX]; p-- > &array[0]; )
or something similar.

Please, no flames about Intel's architecture. I've heard them all for years.

The best way to learn to write portable code is to be required to port
your applications to Vaxes, 68000s, and PCs. (I have all 3 on my desk!)

Rahul Dhesi

unread,
Aug 29, 1988, 4:47:16 PM8/29/88
to
In article <16...@dataio.Data-IO.COM> bri...@dataio.Data-IO.COM (Walter Bright)
writes:

>The best way to learn to write portable code is to be required to port
>your applications to Vaxes, 68000s, and PCs. (I have all 3 on my desk!)

And VAX/VMS specifically. Until you've ported to VMS you haven't
ported. Really.
--
Rahul Dhesi UUCP: <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

T. William Wells

unread,
Aug 30, 1988, 3:15:10 AM8/30/88
to
In article <16...@dataio.Data-IO.COM> bri...@dataio.Data-IO.COM (Walter Bright) writes:
: The best way to learn to write portable code is to be required to port

: your applications to Vaxes, 68000s, and PCs. (I have all 3 on my desk!)

We find that using 68000's (Suns and Macintoshes) and IBM-PC's
(in the various memory models) is sufficient to catch most
portability problems. Especially since we avoid as much as
possible using system provided libraries and do not do terminal
I/O except through standard I/O.

Anybody else have suggestions on sets of systems for checking
portability? And how about portability between different system
libraries and different terminal handling schemes, a problem we
don't (yet) have because we ignore it?

---
Bill
novavax!proxftl!bill

Marty Fouts

unread,
Aug 30, 1988, 11:56:45 AM8/30/88
to

I have the (mis)fortune of having access to a wide range of machines,
and find that portability issues fall into about four catagories: (for
me, your milage may vary)

1) floating header files (where is struct mumble defined, where does
header file bletch.h live, etc.)

2) library differences (is it in libc, or libm, is it strchr or
rindex, does it exist or do I have to carry my own version along. . .)

3) Implementation problems (working around bugs in the system. . .)

4) Architecture dependencies due to language design or implementation
decisions left to the implementer. (it worked on my brand x, but
after I tried it on brand y, I went back and read K&R and sure
enough its not legal. . .)

The rude fact is that the first three can't be covered by any small
set of machines, although a fairly good aproximation can be made by
trying a System V machine, a BSD machine, an MS-DOS machine, and a non-
un*x machine. (VAX/VMS, Apollo)

As far as the fourth goes, I have been bitten by the following
collection of dumb assumptions:

1) byte ordering
2) word size
3) "all pointers are == char *"
4) calling stack implementation
5) assuming a linear address space without holes

My collection of machines which ring out these problems is fairly
small, but probably not widely accessable. I find that I can get by
with only three machines to cover all of the dumb assumptions: A Vax
11/780, a Cray 2, and an Silicon Graphics Iris 4D. The Cray system
seriously strains dumb assumptions in 1-3 and 5, and the Iris gets 4.

Without the 2, a much larger collection of machines would be needed,
but I suspect that a lot could be accomplished with an IBM PC and a
SUN-3 as an alternative.

Anyway, I don't assume that code I've written is reasonably portable,
until it compiles and appears to work on 16, 32 and 64 bit machines of
varying byte order, memory model and calling stack implementation, and
then I only assume that it is reasonably portable and that I've blown
it for the next class of machines I'm going to see. This is a very
healthy paranoia to develop.

Marty

+-+-+-+ I don't know who I am, why should you? +-+-+-+
| fo...@lemming.nas.nasa.gov |
| ...!ames!orville!fouts |
| Never attribute to malice what can be |
+-+-+-+ explained by incompetence. +-+-+-+

Chip Salzenberg

unread,
Aug 30, 1988, 1:27:12 PM8/30/88
to
According to bi...@proxftl.UUCP (T. William Wells):

>We find that using 68000's (Suns and Macintoshes) and IBM-PC's
>(in the various memory models) is sufficient to catch most
>portability problems.

You forgot the best one: any '286 running SCO Xenix System V.
I like to refer to my machine as a portability test with a power switch.
--
Chip Salzenberg <ch...@ateng.uu.net> or <uunet!ateng!chip>
A T Engineering My employer may or may not agree with me.
The urgent leaves no time for the important.

Damian Cugley

unread,
Aug 30, 1988, 4:18:02 PM8/30/88
to
... if you want to index an array starting at one, but

int b[4], *bb = &b[-1];

and variations thereof are interdit, why not use

int bb[5];

Before I am flamed to death for wasting *four* *whole* *bytes* of memory,
I think I can claim excemption under the `speed-vs-space' banner.
Using a pointer as an array probably involves an extra instruction or
CPU cycle somewheres - and `#define bb(x) (b[(x)-1])' does countless
`invisible' subtractions...

pdc

Rob Carriere

unread,
Aug 30, 1988, 5:31:59 PM8/30/88
to
In article <16...@dataio.Data-IO.COM> bri...@dataio.Data-IO.COM (Walter Bright)
writes:
>In article <5...@accelerator.eng.ohio-state.edu> r...@kaa.eng.ohio-state.edu
>(Rob Carriere) writes:
><In article <13...@mimsy.UUCP< ch...@mimsy.UUCP (Chris Torek) writes:
><< [ still on the b = malloc( foo ); bb = b - 1; code in NumRecipes ]
>< [ claiming astonishment in accordance with the Least of.. Principle ]

>On a segmented architecture, like 8086's, malloc can and does return
>a value that is a pointer to the beginning of a segment.
Yes, and as I've written people who e-mailed me this argument, that
spells out ``broken compiler'' if it gives problems ('cause you can't
malloc more than 64K that way). Of course on a machine with large
segments, the counterargument doesn't quite hold water either, so...
>[ unItelligent CPU explanation deleted ]

> array = malloc(MAX * sizeof(array[0]));
> for (p = &array[MAX-1]; p >= &array[0]; p--)

No! That wasn't the problem! (Wish it was, that'd be easy to
avoid!).

The problem is that the authors of Numerical Recipes (NR) observe,
correctly, that many numerical problems are naturally non-zero based.
This gives you the choice between carrying around boatloads of index
arithmatic (inefficient and error-prone), or making non-zero based
arrays. They opt for the latter, in the following way:

float *my_vec; /* this is going to be a vector */
int nl, nh;
...
my_vec = vector( nl, nh ); /* allocates a vector with lowest valid
index nl, and highest valid index nh
*/
...
my_vec[3] = foo(bar);
...

Where we have:

float *vector( nl, nh )
int nl;
int nh;
{
float *v;

v = (float *)malloc( ( nh-nl +1 )* sizeof(float) );
if( v == 0 ) nrerror( "Allocation error in vector()" );

return v - nl;
}

This is quite a bit more disciplined than the example above; it is
also quite bit more fundamental. Fortunately, as far as I've checked
at least, NR only uses vectors and matrices with either 0 or unit
offset, so on broken architectures you could always do

malloc( (nh + 1 )* sizeof(float) );

return v;

This would waste a float per vector, and a pointer-to-float plus n
floats for an n-by-something matrix. Ugly, but it works. (and we
*are* the throw-away culture after all :-)

Rob Carriere

Doug Gwyn

unread,
Aug 31, 1988, 5:07:06 AM8/31/88
to
>>Such an implementation will ABORT ON THE COMPUTATION `b - 1',
>So the standard says, they tell me. It is also one the more flagrant
>violations of the Principle of Least Astonishment I've seen in a
>while.

Sorry, but reality is sometimes astonishing.
That is not an X3J11 invention, just an acknowledgement of the
way the world is. (For example, segmented architectures.)

>Gentlemen >system programmers, surely you too have algorithms that are
>more accurately expressed with arrays from other than base zero?

I doubt that even lady system programmers have much trouble with
0-based arrays.

Doug Gwyn

unread,
Aug 31, 1988, 6:23:33 AM8/31/88
to
In article <5...@accelerator.eng.ohio-state.edu> r...@kaa.eng.ohio-state.edu (Rob Carriere) writes:
>The problem is that the authors of Numerical Recipes (NR) observe,
>correctly, that many numerical problems are naturally non-zero based.

INcorrectly! I've written a lot of array/matrix code in both
Fortran and C, and have found that it normally doesn't matter
and in those cases where it does matter, it doesn't matter much.

I've known mathematicians who have switched over to starting
enumerating at 0 instead of 1. They argued that THAT was "more
natural". One can certainly get used to either convention.

David Dyer-Bennet

unread,
Aug 31, 1988, 11:28:33 AM8/31/88
to
In article <6...@proxftl.UUCP> bi...@proxftl.UUCP (T. William Wells) writes:
>In article <16...@dataio.Data-IO.COM> bri...@dataio.Data-IO.COM (Walter Bright) writes:
>: The best way to learn to write portable code is to be required to port
>: your applications to Vaxes, 68000s, and PCs. (I have all 3 on my desk!)
>
>We find that using 68000's (Suns and Macintoshes) and IBM-PC's
>(in the various memory models) is sufficient to catch most
>portability problems.
>
>Anybody else have suggestions on sets of systems for checking
>portability?
No portability check is complete until you've tried some word-oriented
rather than byte-oriented system. Preferrably something with a word-size
not a multiple of 8 bits (like 60, or 36). CDC, Unisys, Honeywell, and of
course the DEC PDP-10 series all come to mind.
Also, while I haven't tried it personally, I remember a LONG string of
articles years ago in some group with the subject "Porting to PRIME seen
as a probable negative experience"; I seem to remember it has to do with
different types of pointers being of different sizes, none of which would
fit in in an int.

--
-- David Dyer-Bennet
...!{rutgers!dayton | amdahl!ems | uunet!rosevax}!umn-cs!ns!ddb
d...@Lynx.MN.Org, ...{amdahl,hpda}!bungia!viper!ddb
Fidonet 1:282/341.0, (612) 721-8967 hst/2400/1200/300

Rob Carriere

unread,
Aug 31, 1988, 11:48:49 PM8/31/88
to
In article <84...@smoke.ARPA> gw...@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <5...@accelerator.eng.ohio-state.edu> r...@kaa.eng.ohio-state.edu
>(Rob Carriere) writes:
>>The problem is that the authors of Numerical Recipes (NR) observe,
>>correctly, that many numerical problems are naturally non-zero based.
^^^^^^^^^^^^^^^^^^

>INcorrectly! I've written a lot of array/matrix code in both
^^^^^^^^^^^^^^^^^

>Fortran and C, and have found that it normally doesn't matter
>and in those cases where it does matter, it doesn't matter much.

Trivial refutation time! Surely it is obvious that ``numerical
problems'' forms a (large) superset of ``array/matrix code'' as far as
numerical analysis is concerned?

Believe it or not, but there are *many* algorithms out there where
it's either base-1 indexing or index arithmatic all over the place.
Not with your traditional LU-decomposition stuff and so on, but with
algorithms where the contents or properties of the matrix elements are
computed from the indeces.

Rob Carriere

Doug Gwyn

unread,
Sep 1, 1988, 2:43:06 AM9/1/88
to
In article <5...@accelerator.eng.ohio-state.edu> r...@raksha.eng.ohio-state.edu (Rob Carriere) writes:
>Trivial refutation time! Surely it is obvious that ``numerical
>problems'' forms a (large) superset of ``array/matrix code'' as far as
>numerical analysis is concerned?

Trivial indeed! If the code does not involve arrays/matrices,
the issue of 0-based or 1-based indexing doesn't even arise.

Richard Harter

unread,
Sep 1, 1988, 3:46:46 AM9/1/88
to
In article <7...@ns.UUCP> d...@ns.UUCP (David Dyer-Bennet) writes:

> Also, while I haven't tried it personally, I remember a LONG string of
>articles years ago in some group with the subject "Porting to PRIME seen
>as a probable negative experience"; I seem to remember it has to do with
>different types of pointers being of different sizes, none of which would
>fit in in an int.

This is somewhat of a bum rap. Prime C at one time had 48 bit
char pointers versus 32 bit word pointers. Currently all pointers are
48 bits. This makes for problems for people who blithely stuff pointers
into ints. But it really isn't a problem for people who port from UNIX
to PRIMOS who run their code through lint (and act on the results).

Primos C does have some oddities. They set the high bit on in
ascii chars. Setting a file pointer to stdin or stdout has to be done
at the top level. Library routines sometimes have different calling
sequences. There is a 128K limit on array sizes (machine architecture).
But it really isn't all that bad; I've never seen the C compiler break
on standard portable C which is more than I can say for VMS C.

--

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

Johan Vromans

unread,
Sep 1, 1988, 9:05:25 AM9/1/88
to
From article <6...@proxftl.UUCP>, by bi...@proxftl.UUCP (T. William Wells):

> Anybody else have suggestions on sets of systems for checking
> portability?

I have used an Hewlett-Packard HP9000 model 500, which has a very
strange memory architecture (uses non-contiguous memory
segments), and a real stack (which means that uninitialized local variables
contain a zero). Emacs cannot run on it.

There exists a Pr1me system which always has the high bit
of each byte set, so ASCII runs from 128 to 255.

Of course, EBCDIC machines catch most of the programs which
avoided <ctype.h> but use ('a' <= x && x <= 'z') , and segmented
memory machines (like PC's with large model) catch all programs
that (mis)use ints and pointers and longs.

--
Johan

Steven Ryan

unread,
Sep 1, 1988, 4:21:52 PM9/1/88
to
>Anybody else have suggestions on sets of systems for checking
>portability? And how about portability between different system
>libraries and different terminal handling schemes, a problem we
>don't (yet) have because we ignore it?

I would think Vaxes, IBM-PCs, Suns, and Macs are somewhat incestuous.
If you have the money and are interested in the market, you might try
some radically different hardware and operating systems like mainframe
IBM, Cray, CDC, Fujitsu,.....

David Collier-Brown

unread,
Sep 2, 1988, 8:27:39 AM9/2/88
to
>>In article <16...@dataio.Data-IO.COM> bri...@dataio.Data-IO.COM (Walter Bright) writes:
>>: The best way to learn to write portable code is to be required to port
>>: your applications to Vaxes, 68000s, and PCs. (I have all 3 on my desk!)

From article <7...@ns.UUCP>, by d...@ns.UUCP (David Dyer-Bennet):


> No portability check is complete until you've tried some word-oriented
> rather than byte-oriented system. Preferrably something with a word-size
> not a multiple of 8 bits (like 60, or 36). CDC, Unisys, Honeywell, and of
> course the DEC PDP-10 series all come to mind.

Actually the 9-bit byte machines are fairly easy to port to: all
sorts of code of varying quality will run on the Honeywell-Bull
DPS-8 using the Waterloo C Compiler. Try a machine with funny
pointer lengths like the DPS-6, though... Its an 8-bit byte, but
char pointers are 48 bits and others are 32, if you use to high an
address the system will trap even loading a register, etc, etc.

--dave (Bell labs had a DPS-8 C compiler many moons ago) c-b
--
David Collier-Brown. |{yunexus,utgpu}!geac!lethe!dave
78 Hillcrest Ave,. | He's so smart he's dumb.
Willowdale, Ontario. | --Joyce C-B

Roger B.A. Klorese

unread,
Sep 2, 1988, 10:29:40 AM9/2/88
to
In article <23...@mhres.mh.nl> j...@mhres.mh.nl (Johan Vromans) writes:
>From article <6...@proxftl.UUCP>, by bi...@proxftl.UUCP (T. William Wells):
>> Anybody else have suggestions on sets of systems for checking
>> portability?
>There exists a Pr1me system which always has the high bit
>of each byte set, so ASCII runs from 128 to 255.

Yes, *all* of 'em.

(At least, all of the "50 Series" proprietary processors.)
--
Roger B.A. Klorese MIPS Computer Systems, Inc.
{ames,decwrl,prls,pyramid}!mips!rogerk 25 Burlington Mall Rd, Suite 300
rog...@mips.COM (rogerk%mips...@ames.arc.nasa.gov) Burlington, MA 01803
I don't think we're in toto any more, Kansas... +1 617 270-0613

Vidhyanath K. Rao

unread,
Sep 2, 1988, 2:48:12 PM9/2/88
to
In article <83...@smoke.ARPA>, gw...@smoke.ARPA (Doug Gwyn ) writes:
> [From way past]

Such an implementation will ABORT ON THE COMPUTATION `b - 1',
> That is not an X3J11 invention, just an acknowledgement of the
> way the world is. (For example, segmented architectures.)

But why should it abort? If the address is sr:0, (sr = segment register)
subtract 1 to get (sr-1):ffff [or whatever number of 'f's]. Memory
protection, it seems to me, should not notice attempts to compute addresses
but only attempts to access forbidden addresses.

Of course, this approach levies heavy penalities on segmented architecutres.
If you are using the 'small' model (in the 8088 meaning of the word),
sr:0 - 1 = sr:ffff. Now you got to worry about the model. But doesn't the
philosophy of C say 'programmer knows best'. If you want to diddle with
segmented architectures, you got to put up with headaches.

So what am I missing?
-Nath
v...@osupyr.mast.ohio-state.edu

Vidhyanath K. Rao

unread,
Sep 2, 1988, 2:57:29 PM9/2/88
to
In article <84...@smoke.ARPA>, gw...@smoke.ARPA (Doug Gwyn ) writes:
> I've known mathematicians who have switched over to starting
> enumerating at 0 instead of 1. They argued that THAT was "more
> natural". One can certainly get used to either convention.

A mathematician is one who starts counting at 0 :-)
Historically, people were suspicious of 'nothing' which is why 0 was not
a number by itself (as opposed to being used in place value notation) till
about 6th century A.D.
As far as indexing goes where one starts makes a difference in terms of
typography :-) More seriously, one may have several things to be indexed,
over a big range (-infinity to infinity even) and each thing is indexed
over some subrange not starting at 0. Changing every origin to 0 is
painful and likely to lead to bugs. Ideally this must be fixed up at the
preprocessor level than at code level. Anybody want to write these
macros?
-Nath
v...@osupyr.mast.ohio-state.edu

David Collier-Brown

unread,
Sep 4, 1988, 10:06:20 AM9/4/88
to
> In article <83...@smoke.ARPA>, gw...@smoke.ARPA (Doug Gwyn ) writes:
>> [From way past]
> Such an implementation will ABORT ON THE COMPUTATION `b - 1',
>> That is not an X3J11 invention, just an acknowledgement of the
>> way the world is. (For example, segmented architectures.)

From article <8...@osupyr.mast.ohio-state.edu>, by v...@osupyr.mast.ohio-state.edu (Vidhyanath K. Rao):

> But why should it abort? If the address is sr:0, (sr = segment register)
> subtract 1 to get (sr-1):ffff [or whatever number of 'f's]. Memory
> protection, it seems to me, should not notice attempts to compute addresses
> but only attempts to access forbidden addresses.

Regrettably, some architectures prohibit this: (sr-1):ffff may
mean <undefined segment>:ffff, and the loading of the selector into an
selector register will cause a fault. The basic idea here is that
the operating system pre-fetches a page or segment on being informed
that the program is "about" to need it, as indicated by loading its
selector into a distinguished register.
This behavior is possible on the Honeywell DPS-6[1], and certainly
on an Intel machine running a non-DOS operating system.

--dave (@lethe) c-b
[1] I think the compiler writers watch out for this happening, but
I do know that it makes compiler- & debugger-writing **difficult**.
Anyone from SDG want to comment?
--
David Collier-Brown. | yunexus!lethe!dave

Dave Caswell

unread,
Sep 4, 1988, 6:11:56 PM9/4/88
to
In article <23...@mhres.mh.nl> j...@mhres.mh.nl (Johan Vromans) writes:

.I have used an Hewlett-Packard HP9000 model 500, which has a very
.strange memory architecture (uses non-contiguous memory
.segments), and a real stack (which means that uninitialized local variables
.contain a zero). Emacs cannot run on it.
^^^^^^^^^^^^^^^^^^^^^^^
Nonsense, many people use Emacs on HP9000/500.

--
Dave Caswell
Greenwich Capital Markets uunet!philabs!gcm!dc

Craig Jackson

unread,
Sep 4, 1988, 7:13:56 PM9/4/88
to
In article <8...@osupyr.mast.ohio-state.edu> v...@osupyr.mast.ohio-state.edu (Vidhyanath K. Rao) writes:
>In article <83...@smoke.ARPA>, gw...@smoke.ARPA (Doug Gwyn ) writes:
>> [From way past]
> Such an implementation will ABORT ON THE COMPUTATION `b - 1',
>> That is not an X3J11 invention, just an acknowledgement of the
>> way the world is. (For example, segmented architectures.)
>
>But why should it abort? If the address is sr:0, (sr = segment register)
>subtract 1 to get (sr-1):ffff [or whatever number of 'f's]. Memory
>protection, it seems to me, should not notice attempts to compute addresses
>but only attempts to access forbidden addresses.

There exist machines whose protection philosophy is to prevent you from
even thinking something illegal. In particular, on the Unisys A-series,
the compiler must implement all memory addressing protection--there is
no kernel/user state protection on memory.* A program cannot be allowed
to form an invalid address, as there is nothing to stop it from using it,
and nothing in the hardware to stop you from stomping on another user
if you do. Therefore, the compiler and the operating system would be
written so as to cause an interrupt if computing 'b - 1' were attempted.
The ANSI rules were written to allow C to be implemented on such an
architecture.

Note that there is no C compiler for the A-series today, although one is
rumored. The rumors say that arrays and pointers will not be implemented
this way, however. In order to get around some other problems, and to allow
more old programs to run, a linear-address space machine will be simulated,
using a large array. (Arrays are hardware concepts on the A-series.)

>Of course, this approach levies heavy penalities on segmented architecutres.

On some architectures, it may be an infinite penalty--C could not be
implemented. Or maybe only by simulating a more PDP-11-like machine
(as discussed above).

>If you are using the 'small' model (in the 8088 meaning of the word),
>sr:0 - 1 = sr:ffff. Now you got to worry about the model. But doesn't the
>philosophy of C say 'programmer knows best'. If you want to diddle with
>segmented architectures, you got to put up with headaches.

You sometimes have to, in order to get some benefits (like having your
OS written in a really high-level language, with no assembler, etc.)

>So what am I missing?

A broad education in the corners of the computer architecture world.

>-Nath
>v...@osupyr.mast.ohio-state.edu

* Note that putting the protection in the compiler was also an idea
of Per Brinch-Hansen's in the 1970s, with Concurrent Pascal. Burroughs
had been doing it for many years, even then.
--
Craig Jackson
UUCP: {harvard!axiom,linus!axiom,ll-xn}!drilex!dricej
BIX: cjackson

Johan Vromans

unread,
Sep 6, 1988, 5:43:09 AM9/6/88
to
From article <5...@white.gcm>, by dc@gcm (Dave Caswell):

> In article <23...@mhres.mh.nl> j...@mhres.mh.nl (Johan Vromans) writes:
> .I have used an Hewlett-Packard HP9000 model 500, which has a very
> .strange memory architecture (uses non-contiguous memory
> .segments), and a real stack (which means that uninitialized local variables
> .contain a zero). Emacs cannot run on it.
> ^^^^^^^^^^^^^^^^^^^^^^^
> Nonsense, many people use Emacs on HP9000/500.

A quote from the file etc/MACHINES of the GNU 18.50 distribution:

"The [HP9000] series 500 has a seriously incompatible memory architecture
"which relocates data in memory during execution of a program,
"and support for it would be difficult to implement.

Of course, "other" emacses are available for HP9000 model 500
(MicroEmacs, Jove, Scame, Unipress??).


--
Johan

Steve Fullerton

unread,
Sep 6, 1988, 10:29:08 AM9/6/88
to
In article <5...@white.gcm> d...@white.UUCP (Dave Caswell) writes:
>In article <23...@mhres.mh.nl> j...@mhres.mh.nl (Johan Vromans) writes:
>
>.I have used an Hewlett-Packard HP9000 model 500, which has a very
>...

>.contain a zero). Emacs cannot run on it.
> ^^^^^^^^^^^^^^^^^^^^^^^
>Nonsense, many people use Emacs on HP9000/500.
>

I believe he is probably referring to GNU Emacs which definitely does
not run on the HP9000/500. There are even references to this fact in
the installation/porting documentation.

About a 15 months ago I ordered Emacs from Unipress software as they said
an HP9000/500 version was available. `Available' meant that they sent out
a source tape with some comments for the HP9000/500. I spent several days
to get to a running version but it was so buggy that everything was boxed
up and returned within the week. Maybe they have it working now...

--
Steve Fullerton Statware, Inc.
scf%statwa...@cs.orst.edu 260 SW Madison Ave, Suite 109
orstcs!statware!scf Corvallis, OR 97333
503/753-5382

Chris Torek

unread,
Sep 6, 1988, 10:33:56 AM9/6/88
to
[me, paraphrased by me:]
>An implementation may ABORT ON THE COMPUTATION of an illegal address.

In article <8...@osupyr.mast.ohio-state.edu> v...@osupyr.mast.ohio-state.edu
(Vidhyanath K. Rao) asks:


>But why should it abort? If the address is sr:0, (sr = segment register)
>subtract 1 to get (sr-1):ffff [or whatever number of 'f's].

On many machines, addresses are unsigned numbers. The domain and range
of an unsigned 16-bit number is 0..65535. What is the (mathematical)
result of 0 - 1? Answer: -1. Is it in range? No. So what happens?
Integer underflow, which on many machines is a trap.

You can even do this on a VAX, although there you must first enable the
trap (use bispsw or set the appropriate flag in the subroutine entry
mask), and then it only fires on integer computations outside the range
-2 147 483 648..2 147 483 647; so if (for instance) you were to write

main()
{
char *p;

p = (char *)0x7fffffff;
asm("bispsw $0x20"); /* PSL_IV */
p++;
}

This program, when run, aborts with a `floating exception' (SIGFPE).
It would be legal for the C compiler to set IV in the entry point
of each subroutine, although it would probably break too much code
that expects integer overflow/underflow to be ignored, and the code
that does C's `unsigned' arithmetic would have to turn it off temporarily.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: ch...@mimsy.umd.edu Path: uunet!mimsy!chris

Don Libes

unread,
Sep 7, 1988, 7:40:26 PM9/7/88
to
Please don't spend too much time debating the code in this book. The
authors were Fortran programmers who learned C simply to write this
book. It isn't surprising that they are confusing readers.

I am told that the original Fortran/Pascal version is a good book, but
they clearly could have used some help with this version. I
appreciate that they tried to explain and point out the problems of
numerical programming in C, but they often criticize or make uncalled
for assumptions about C due to their ignorance.

For example, the following is a quote from a recent issue of
Micro/Systems Journal which reviewed the book:

They suggest not using switch-case-default construction, ...
because they consider the structure confusing, and also "burdened
by uncertainty, from compiler to compiler about what data types
are allowed in its control expression." It is recommended that
this be replaced by "a more recognizable and translatable if-else
construction."

They [NRC] go on to make many other unfounded remarks, such as "avoid
continue;". Isn't there a better book for numerical programming in C?

Don Libes cme-durer.arpa ...!uunet!cme-durer!libes

Peter da Silva

unread,
Sep 7, 1988, 9:52:09 PM9/7/88
to
In article <6...@drilex.UUCP>, dri...@drilex.UUCP (Craig Jackson) writes:
> * Note that putting the protection in the compiler was also an idea
> of Per Brinch-Hansen's in the 1970s, with Concurrent Pascal. Burroughs
> had been doing it for many years, even then.

What's to stop you from doing the following:

Generate code in an array.
Jump to the beginning of the array. *

Now you've blown the protection. You can do anything. I hope this isn't a
multiuser machine...

* this may involve such things as passing a pointer to an array to a
function that's declared that argument as a pointer to a function, or
even by writing the array out as a file and executing it... I can't see
how you could write a valid 'C' compiler that wouldn't let you violate
this protection.
--
Peter da Silva `-_-' Ferranti International Controls Corporation.
"Have you hugged U your wolf today?" pe...@ficc.uu.net

Peter da Silva

unread,
Sep 7, 1988, 10:02:01 PM9/7/88
to
In article <32...@geac.UUCP>, da...@geac.UUCP (David Collier-Brown) writes:
> Regrettably, some architectures prohibit this: (sr-1):ffff may
> mean <undefined segment>:ffff, and the loading of the selector into an
> selector register will cause a fault.

But nobody says you have to load the selector into a selector register
just to compute an address. Why should the address calculation hardware
be involved at all?

Daniel R. Levy

unread,
Sep 8, 1988, 1:37:41 AM9/8/88
to
In article <23...@mhres.mh.nl>, j...@mhres.mh.nl (Johan Vromans) writes:
> A quote from the file etc/MACHINES of the GNU 18.50 distribution:
>
> "The [HP9000] series 500 has a seriously incompatible memory architecture
> "which relocates data in memory during execution of a program,
> "and support for it would be difficult to implement.

What are the implications of this "relocation of data in memory during
execution" and why would it cause Emacs problems but not problems in
general with C programs which use pointers. (If the HP9000 will move a
block of memory after a pointer to it has been loaded, then the pointer is
now no good... or is it?)
--
|------------Dan Levy------------| THE OPINIONS EXPRESSED HEREIN ARE MINE ONLY
| Bell Labs Area 61 (R.I.P., TTY)| AND ARE NOT TO BE IMPUTED TO AT&T.
| Skokie, Illinois |
|-----Path: att!ttbcad!levy-----|

Dr. T. Andrews

unread,
Sep 8, 1988, 9:41:00 AM9/8/88
to
In article <13...@mimsy.UUCP>, ch...@mimsy.UUCP (Chris Torek) writes:
) main()
) {
) char *p;
)
) p = (char *)0x7fffffff;
) asm("bispsw $0x20"); /* PSL_IV */
) p++;
) }
) This program, when run, aborts with a `floating exception' (SIGFPE).

I may not be the first one to cast a stone at this example, but have
you considered the possibility that a floating point exception is
manifestly the \fBwrong\fP thing to do in your example? There is no
floating-point math in there. Complain to your vendor.
--
...!bikini.cis.ufl.edu!ki4pv!cdis-1!tanner ...!bpa!cdin-1!cdis-1!tanner
or... {allegra killer gatech!uflorida decvax!ucf-cs}!ki4pv!cdis-1!tanner

Dave Caswell

unread,
Sep 8, 1988, 7:32:37 PM9/8/88
to
In article <10...@statware.UUCP> scf%statwa...@cs.orst.edu (Steve Fullerton) writes:
.About a 15 months ago I ordered Emacs from Unipress software as they said
.an HP9000/500 version was available. `Available' meant that they sent out
.a source tape with some comments for the HP9000/500. I spent several days
.to get to a running version but it was so buggy that everything was boxed
.up and returned within the week. Maybe they have it working now...

The version of Gosling Emacs we have is datad 1985.

Chris Torek

unread,
Sep 8, 1988, 9:05:35 PM9/8/88
to
-In article <6...@drilex.UUCP> dri...@drilex.UUCP (Craig Jackson) writes:
->* Note that putting the protection in the compiler was also an idea
->of Per Brinch-Hansen's in the 1970s, with Concurrent Pascal. Burroughs
->had been doing it for many years, even then.

In article <14...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
-What's to stop you from doing the following:
-
- Generate code in an array.
- Jump to the beginning of the array. *

Whenever the compiler is forced to generate `iffy' code, it also generates
tests such as tags to make sure that you do not do something like this.

Rob Carriere

unread,
Sep 8, 1988, 9:37:46 PM9/8/88
to
In article <6...@muffin.cme-durer.ARPA> li...@cme-durer.arpa (Don Libes) writes:
> [ Numerical Recipes in C is FORTRAN translated by people who don't
> quite know what they are talking about; evidence from a review in
> Micro/Systems Journal that quotes matter from the introductory
> chapter.
> ]

> Isn't there a better book for numerical programming in C?

The FORTRAN origins of the NRC code are at points quite clear, there
are several routines that could easily have been coded base 0, and
were coded base 1, and so on. The introductory chapter contains
several remarks about C that to the experienced C programmer, and even
to me, sound rather inane. All true.

However, I do not know of any book, in *any* language, that contains
the quality and quantity of numerical material that NRC has. You
should take into account that good numerical analysis is more than 80%
math, so even if the programming job were botched (and it isn't), the
book would be worth its money. Further, apart from the base-0/base-1
array issue that has been beaten to death in this group already, the
actual C code (as opposed to their philosophy about it) is good. The
reason for this is simply that while numerical code may have very
intricate analysis behind it, the actual code tends to be rather
simple -- a couple of for loops and a handful of if's is typical.

Finally, the problem with the base-1 arrays can simply be solved by a
minor change to the vector(), dvector(), ivector(), matrix(),
dmatrix() and imatrix() code, with a corresponding change in the
free_<vector, etc> routines. I posted the change for vector() a while
ago.

In summary, anyone who claims the book to be of little or no value is
not doing it justice.


Rob Carriere

Hans Zuidam

unread,
Sep 9, 1988, 3:54:08 AM9/9/88
to
In article <29...@ttrdc.UUCP> le...@ttrdc.UUCP (Daniel R. Levy) writes:
>In article <23...@mhres.mh.nl>, j...@mhres.mh.nl (Johan Vromans) writes:
>> A quote from the file etc/MACHINES of the GNU 18.50 distribution:
>>
>> "The [HP9000] series 500 has a seriously incompatible memory architecture
>> "which relocates data in memory during execution of a program,
>> "and support for it would be difficult to implement.

(This is from memory)
When I worked at the Eindhoven University of Technology we had 4 HP9000/500s
and we ported emacs to it.

The real problem (with emacs 16.??) we had was that emacs assumed that a machine
with 32 bit words uses only 24 address bits. The upper 8 were assumed to be free
and available for type tags. In essence, it assumed that all machines have a VAX
like addressing scheme. The HP9000/500 uses all 32 bits. This same problem
occurred every time we tried to port a program which made any assumption on the
format of a pointer.

The "problem" is that the HP9000/500 has a segmented memory architecture. Each
pointer consists of a segment number and a segment offset and then some. At load
time the segments are assigned to the program and each pointer (identified as
such in the load file) is fixed up with the segment number of its associated data.
When you have emacs dump itself to create a faster loadable binary, you would
have to write every pointer back with no segment assigned. For arbitrary pointers
this is a hell of a job.

A colleague of mine succeeded in porting it but without the dump facility. If
you are interrested, you can contact him at the following address:

Geert Leon Janssen
Eindhoven University of Technology,
Department of Electrical Engineering,
P.O. Box 513,
5600 MB Eindhoven, The Netherlands.
(UUCP: ...!mcvax!euteal!geert)
--
Hans Zuidam E-Mail: ha...@nlgvax.UUCP
Philips Telecommunications and Data Systems, Tel: +31 40 892288
Project Centre Geldrop, Building XR
Willem Alexanderlaan 7B, 5664 AN Geldrop The Netherlands

Doug Gwyn

unread,
Sep 9, 1988, 2:57:47 AM9/9/88
to
In article <14...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
>What's to stop you from doing the following:
> Generate code in an array.
> Jump to the beginning of the array. *
>... I can't see how you could write a valid 'C' compiler that wouldn't
>let you violate this protection.

That's simple. All the compiler has to do is detect any attempt to
use a data object as a function. The only way to even attempt this in
standard C is via an explicit cast to a function pointer somewhere,
which is where the compiler would enforce the constraint.

Johan Vromans

unread,
Sep 9, 1988, 4:23:47 AM9/9/88
to
From article <29...@ttrdc.UUCP>, by le...@ttrdc.UUCP (Daniel R. Levy):

> What are the implications of this "relocation of data in memory during
> execution" and why would it cause Emacs problems but not problems in
> general with C programs which use pointers. (If the HP9000 will move a
> block of memory after a pointer to it has been loaded, then the pointer is
> now no good... or is it?)

As I remember ... an pointer on the HP9000/500 system is
something you cannot treat as an numeric quantity. Of course, you
should not do that anyway.
I recall the following symptoms:
- address space is not contiguous from zero to somewhere,
pointers contain segment numbers and offsets;
- you cannot store a pointer on disk, and read it back in
another run, because your program will probably not be loaded
in the same memory segments;
- you cannot use the highest bits of a pointer for other
purposes (as GNU Emacs does). All 32 bits contain information.

When you use pointers thru C (e.g. "ptr1 - ptr2" or "ptr[index]")
everything goes well, that's why "normal" applications are not
affected.

Another feature of the HP9000/500 is that local variables are
garanteed to contain 0 (zero) at startup.
--
Johan

Chris Torek

unread,
Sep 9, 1988, 1:13:36 PM9/9/88
to
>In article <13...@mimsy.UUCP> I noted that you can make the VAX trap
on integer overflow:

>) asm("bispsw $0x20"); /* PSL_IV */
>) p++;
>)This program, when run, aborts with a `floating exception' (SIGFPE).

In article <70...@cdis-1.uucp> tan...@cdis-1.uucp (Dr. T. Andrews) writes:
>I may not be the first one to cast a stone at this example, but have
>you considered the possibility that a floating point exception is
>manifestly the \fBwrong\fP thing to do in your example? There is no
>floating-point math in there. Complain to your vendor.

What would you have it called? Here are the possible signals:

#define SIGHUP 1 /* hangup */
#define SIGINT 2 /* interrupt */
#define SIGQUIT 3 /* quit */
#define SIGILL 4 /* illegal instruction (not reset when caught) */
#define SIGTRAP 5 /* trace trap (not reset when caught) */
#define SIGIOT 6 /* IOT instruction */
#define SIGABRT SIGIOT /* compatibility */
#define SIGEMT 7 /* EMT instruction */
#define SIGFPE 8 /* floating point exception */
#define SIGKILL 9 /* kill (cannot be caught or ignored) */
#define SIGBUS 10 /* bus error */
#define SIGSEGV 11 /* segmentation violation */
#define SIGSYS 12 /* bad argument to system call */
#define SIGPIPE 13 /* write on a pipe with no one to read it */
#define SIGALRM 14 /* alarm clock */
#define SIGTERM 15 /* software termination signal from kill */
#define SIGURG 16 /* urgent condition on IO channel */
#define SIGSTOP 17 /* sendable stop signal not from tty */
#define SIGTSTP 18 /* stop signal from tty */
#define SIGCONT 19 /* continue a stopped process */
#define SIGCHLD 20 /* to parent on child stop or exit */
#define SIGCLD SIGCHLD /* compatibility */
#define SIGTTIN 21 /* to readers pgrp upon background tty read */
#define SIGTTOU 22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
#define SIGIO 23 /* input/output possible signal */
#define SIGXCPU 24 /* exceeded CPU time limit */
#define SIGXFSZ 25 /* exceeded file size limit */
#define SIGVTALRM 26 /* virtual time alarm */
#define SIGPROF 27 /* profiling time alarm */
#define SIGWINCH 28 /* window size changes */
#define SIGUSR1 30 /* user defined signal 1 */
#define SIGUSR2 31 /* user defined signal 2 */

You have to squeeze it in somewhere, and in fact the VAX hardware
reports integer overflow and floating exceptions with the same trap /
fault (`arithmetic exception').

Peter da Silva

unread,
Sep 9, 1988, 5:42:49 PM9/9/88
to
In article <13...@mimsy.UUCP>, ch...@mimsy.UUCP (Chris Torek) writes:
> -In article <6...@drilex.UUCP> dri...@drilex.UUCP (Craig Jackson) writes
about Burroughs putting protection in the compiler...

> In article <14...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
> -What's to stop you from doing the following:
> -
> - Generate code in an array.
> - Jump to the beginning of the array. *

Chris Torek noted:

> Whenever the compiler is forced to generate `iffy' code, it also generates
> tests such as tags to make sure that you do not do something like this.

So what's to stop me from writing out a load module and subverting
the protection mechanism, as I noted in my (deleted) footnote? I would
think that the perversions necessary to make 'C' safe to run on this machine
would make it sufficiently useless that a little thing like calculating
a pointer to a position before the beginning of an array is a minor
detail...

That is to say, yes... this construct is non-portable. But only to machines
you would have severe problems porting to in the first place.

Chris Torek

unread,
Sep 10, 1988, 12:56:11 PM9/10/88
to
>In article <13...@mimsy.UUCP> I noted that for such an odd machine,

>>Whenever the compiler is forced to generate `iffy' code, it also generates
>>tests such as tags to make sure that you do not do something like this.

In article <14...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
>So what's to stop me from writing out a load module and subverting
>the protection mechanism, as I noted in my (deleted) footnote?

The O/S, of course, which cooperates with the compiler as to these tags
or region markers or whatever. In fact, the only way to subvert the
system, if the system is done right, is to take it apart and either
rewire it, or move its disks to another machine and rewrite them, or
something along those lines---i.e., something software is physically
unable to protect against. (I thought this whole line of reasoning was
obvious. [proof by intimidation :-) ])

>I would think that the perversions necessary to make 'C' safe to run

>on this machine would make it sufficiently useless ...

Probably.

Bob Larson

unread,
Sep 10, 1988, 1:51:56 PM9/10/88
to
In article <14...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
>In article <13...@mimsy.UUCP>, ch...@mimsy.UUCP (Chris Torek) writes:
>> In article <14...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
>> -What's to stop you from doing the following:
>> - Generate code in an array.
>> - Jump to the beginning of the array. *

Decent memory protection. (There are those of us who believe that
executable and writable memory should be mutually exclusive. (with a
provision to change from one to the other.))

>So what's to stop me from writing out a load module and subverting
>the protection mechanism, as I noted in my (deleted) footnote?

The same type of protection mechinism that makes it impossible
(or hopefully at least difficult) to alter other users files.
Writing out executalbe files may be considered a priviliged
function reserved to compilers.

(Please note I am not saying that I think that compilers are the proper
place to enforce system security, just that portably written code shouldn't
have undue hardship running on such a machine.)
--
Bob Larson Arpa: Bla...@Ecla.Usc.Edu bla...@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list: info-prime-request%ai...@ecla.usc.edu
oberon!ais1!info-prime-request

Craig Jackson

unread,
Sep 10, 1988, 7:42:49 PM9/10/88
to
In article <14...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
>In article <6...@drilex.UUCP>, dri...@drilex.UUCP (Craig Jackson) writes:
>> * Note that putting the protection in the compiler was also an idea
>> of Per Brinch-Hansen's in the 1970s, with Concurrent Pascal. Burroughs
>> had been doing it for many years, even then.
>
>What's to stop you from doing the following:
>
> Generate code in an array.
> Jump to the beginning of the array. *
>
>Now you've blown the protection. You can do anything. I hope this isn't a
>multiuser machine...

Two things stop this:

1. There's no way to 'say it'; see below.

2. There is a tag field on each word of memory. Data has a tag of 0 or 2;
code has a tag of 3. It is the responsibility of the compiler to make sure
that a user program cannot set its own tags. Only the operator can turn
a program into a compiler, and only a compiler can create an object program.

(There are, of course, holes for people with super-user-like privileges.
Just like Unix.)

>* this may involve such things as passing a pointer to an array to a
>function that's declared that argument as a pointer to a function, or
>even by writing the array out as a file and executing it... I can't see
>how you could write a valid 'C' compiler that wouldn't let you violate
>this protection.

Another feature of this system is a type-checking linker. All functions
must agree in number of arguments and type of arguments with their calls.
The linker, called the binder on the A-series, enforces this. (This makes
varargs be a pain in the behind, BTW. One reason why A-series C most likely
will not fully use the hardware, and therefore be a slow, undesirable
language. Much like their PL/I.)

>Peter da Silva `-_-' Ferranti International Controls Corporation.

Sho Kuwamoto

unread,
Sep 11, 1988, 3:01:00 AM9/11/88
to
I *want* to be able to create an array and jump to it. I do this all
the time. Granted, I do this on a micro (a Mac) so first of all, it's
just more feasable, and second of all, there's no sophisticated memory
management (or for that matter, not nearly as much need to worry about
crashing the system) but still, I think it's a bit severe to say that
such a thing should never be done. Maybe it would be OK if the
compiler gave you the option of explicitly coercing some piece of data
into becoming code.

-Sho

der Mouse

unread,
Sep 11, 1988, 7:36:14 AM9/11/88
to
In article <23...@mhres.mh.nl>, j...@mhres.mh.nl (Johan Vromans) writes:
> From article <5...@white.gcm>, by dc@gcm (Dave Caswell):
>> In article <23...@mhres.mh.nl> j...@mhres.mh.nl (Johan Vromans) writes:
>>> Emacs cannot run on it. ["it" = HP9000/500]

>> Nonsense, many people use Emacs on HP9000/500.
> A quote from the file etc/MACHINES of the GNU 18.50 distribution:
> [basically, the HP9000/500 makes it hard for Gnumacs to run]

> Of course, "other" emacses are available for HP9000 model 500

So what's wrong with "many people use Emacs on HP9000/500"? Nobody
(until your posting) said anything about specifically GNU emacs.

der Mouse

old: mcgill-vision!mouse
new: mo...@larry.mcrcim.mcgill.edu

jim nutt

unread,
Sep 12, 1988, 11:27:51 PM9/12/88
to

> From: j...@mhres.mh.nl (Johan Vromans)
> Message-ID: <23...@mhres.mh.nl>

>
> As I remember ... an pointer on the HP9000/500 system is
> something you cannot treat as an numeric quantity. Of course, you
> should not do that anyway.
> I recall the following symptoms:
> - address space is not contiguous from zero to somewhere,
> pointers contain segment numbers and offsets;
> - you cannot store a pointer on disk, and read it back in
> another run, because your program will probably not be loaded
> in the same memory segments;
> - you cannot use the highest bits of a pointer for other
> purposes (as GNU Emacs does). All 32 bits contain information.

actually sounds a lot like working on an intel iapx86 microprocessor, doesn't it? the restrictions are much the same.

jim nutt
'the computer handyman'


--
St. Joseph's Hospital/Medical Center - Usenet <=> FidoNet Gateway
Uucp: ...ncar!noao!asuvax!stjhmc!15.11!jim.nutt

T. William Wells

unread,
Sep 13, 1988, 1:32:34 PM9/13/88
to
In article <1409@pur-phy> s...@newton.physics.purdue.edu.UUCP (Sho Kuwamoto) writes:
: I *want* to be able to create an array and jump to it. I do this all

I'm getting real tired of the "I wanna do X" comments. First,
there is almost (but now always) a better, standard way to do the
same thing. And second, there seems to be a *major*
misunderstanding of what ANSI says.

ANSI does *not* say that you can't jump into your data. All that
it says that this is not guaranteed to work. In other words,
it's nonportable. OF COURSE its nonportable. It's just not
going to work on a machine with a different processor, and it may
not work with a different operating system or a different
compiler.

A similar comment applies to a lot of things that people are
complaining about. ANSI rarely says that, at run time, certain
things are not allowed. Instead, it says things like "if you do
X, the results are undefined (or implementation dependent)".

So you *can* write your incremental compiler and have it conform
to ANSI C (though it will not be maximally conforming). You just
can't do that and assume that it will port. And that is what you
would expect.

Let me make that clear: unless the ANSI standard says that the
compiler *must* prohibit something, that thing is *allowed*. If
there is something reasonable to do on your particular system, so
long as doing it doesn't conflict with the do's and don'ts that
are stated in the standard, the compiler can do it. And you can
use that feature to your hearts content, and have a conforming
program. The program won't be maximally conforming, so it won't
necessarily port easily, but that is the cost of using a system
specific feature.

---
Bill
novavax!proxftl!bill

M.T.Russell

unread,
Sep 15, 1988, 8:40:58 AM9/15/88
to

There is another way to treat a data object as a function:

union foo {
char *data;
int (*func)();
};

The compiler would either have to prohibit unions with both text and
data pointers or do runtime bookkeeping to remember what was last
stored in such unions.

Mark Russell
m...@ukc.ac.uk

Chip Salzenberg

unread,
Sep 15, 1988, 2:50:23 PM9/15/88
to
According to pe...@ficc.uu.net (Peter da Silva):

>But nobody says you have to load the selector into a selector register
>just to compute an address.

More to the point: The dpANS says you (the implementor) are _allowed_ to
load the selector into a selector register when computing the address. To
do otherwise could slow down register-intensive pointer manipulation.

--
Chip Salzenberg <ch...@ateng.uu.net> or <uunet!ateng!chip>
A T Engineering My employer may or may not agree with me.
The urgent leaves no time for the important.

News system

unread,
Sep 16, 1988, 8:25:08 PM9/16/88
to
In article <1988Sep15.1...@ateng.uucp> ch...@ateng.UUCP (Chip Salzenberg) writes:
>According to pe...@ficc.uu.net (Peter da Silva):
>>But nobody says you have to load the selector into a selector register
>>just to compute an address.
>
>More to the point: The dpANS says you (the implementor) are _allowed_ to
>load the selector into a selector register when computing the address. To
>do otherwise could slow down register-intensive pointer manipulation.
>

But consider what might have happened had dpANS mandated that the compution
of a pointer to x[-1] be a valid operation. Then machines for wich the
mandated behavior is slow would be not used by people interested in high
performance. The net effect could be salubrious for the computer industry in
the long run.

Marv Rubinstein

Chris Torek

unread,
Sep 17, 1988, 7:30:04 AM9/17/88
to
In article <16...@ism780c.isc.com> ne...@ism780c.isc.com (News system)

[really Marv Rubinstein in disguise] writes:
>But consider what might have happened had dpANS mandated that the compution
>of a pointer to x[-1] be a valid operation. Then machines for which the

>mandated behavior is slow would be not used by people interested in high
>performance. The net effect could be salubrious for the computer industry
>in the long run.

Perhaps. I, for one, would find it useful to be Officially Allowed to
compute &arr[negative_offset]. I already make use of this (nonportably) in
existing code. There is a second pitfall, however.

Consider the following (not strictly conforming) code:

struct array_descriptor {
int low; /* lower bound */
int bound; /* upper bound - lower bound */
int *data; /* pointer to &data[0] */
};

/*
* Allocate a new array whose subscripts range from [low..high)
*/
struct array_descriptor *new_array(int low, int high) {
struct array_descriptor *p;
int bound, *dp;

/* first get a descriptor */
if ((p = (struct array_descriptor *)malloc(sizeof(*p))) == NULL)
return (NULL);

/* then check for degenerate arrays (no data) */
p->low = low;
if ((bound = high - low) <= 0) {
p->bound = 0;
p->data = NULL;
} else {
/* allocate data */
if ((dp = (int *)malloc(bound * sizeof(*dp))) == NULL) {
free((char *)p);
return (NULL);
}
p->bound = bound;
p->data = &dp[-low]; /* virtual zero point */
}
return (p);
}

If the computation `&dp[-low]' does not over- or under-flow, it
produces some pointer. If `low' is positive, it produces a pointer
that does not point to valid data, but as long as that pointer is
used by adding a value in [low..high) before indirecting, things
should work out.

Now consider the free routine:

void free_array(struct array descriptor *p) {

if (p->data != NULL)
free((char *)(&p->data[p->low]));
free((char *)p);
}

Do you see the hidden assumption here?

if (p->data != NULL)

but p->data is not a `valid' pointer. Maybe we had best write

if (&p->data[p->low] != NULL)

but this is no good either (look again at new_array). At least

if (p->bound)

seems safe. But what *really* happens if, in new_array, &p->data[-low]
turns out to `just happen' to equal NULL?

The approach I used in my own (nonportable) code was to keep the
original pointer around, just in case (and because there was no
p->bound available: allocation of data objects is deferred until they
are needed). This also `just happens' to keep happy some garbage
collecting C runtime systems. The above code, run on such a system,
might fail mysteriously after the garbage collector runs---because the
data pointer computed by &p->data[-100] is outside the region allocated
by malloc. The GC routine would assume it was free, and cheerfully
release it for another malloc().

Peter da Silva

unread,
Sep 17, 1988, 11:58:24 AM9/17/88
to
In article <1988Sep15.1...@ateng.uucp>, ch...@ateng.uucp (Chip Salzenberg) writes:
> According to pe...@ficc.uu.net (Peter da Silva):
> >But nobody says you have to load the selector into a selector register
> >just to compute an address.

> More to the point: The dpANS says you (the implementor) are _allowed_ to
> load the selector into a selector register when computing the address. To
> do otherwise could slow down register-intensive pointer manipulation.

OK, then, I withdraw my objection to the original message. Since
there is no portable method of declaring non-zero-based arrays in 'C',
and since the code generation task for using such is trivial, they should
be added.

Doug Gwyn

unread,
Sep 17, 1988, 4:14:53 PM9/17/88
to
In article <16...@ism780c.isc.com> ma...@ism780.UUCP (Marvin Rubenstein) writes:
-But consider what might have happened had dpANS mandated that the compution
-of a pointer to x[-1] be a valid operation. Then machines for wich the
-mandated behavior is slow would be not used by people interested in high
-performance. The net effect could be salubrious for the computer industry in
-the long run.

I doubt that any effect on the computer industry would have occurred
other than reduced adherence to the postulated C standard. People
writing portable applications would still not be able to compute
&array[-1], since several compilers would ignore that requirement
(benchmark speed is a far greater driving factor than the desires of
a few sloppy programmers to compute non-existent addresses). What
good would that situation accomplish? Better that the standard be
widely followed and that programmers become better educated about
actual portability considerations, than to encourage false hopes for
availability of features that are difficult or detrimental to provide.

Henry Spencer

unread,
Sep 17, 1988, 5:09:15 PM9/17/88
to
In article <55...@eagle.ukc.ac.uk> m...@arthur.UUCP (M.T.Russell) writes:
> union foo {
> char *data;
> int (*func)();
> };
>
>The compiler would either have to prohibit unions with both text and
>data pointers or do runtime bookkeeping to remember what was last
>stored in such unions.

No, it is sufficient if any attempt to use this trick malfunctions badly.
(For example, if the two kinds of pointers are not the same size, it is
almost guaranteed to.)
--
NASA is into artificial | Henry Spencer at U of Toronto Zoology
stupidity. - Jerry Pournelle | uunet!attcan!utzoo!henry he...@zoo.toronto.edu

Henry Spencer

unread,
Sep 17, 1988, 5:20:12 PM9/17/88
to
In article <16...@ism780c.isc.com> ma...@ism780.UUCP (Marvin Rubenstein) writes:
>But consider what might have happened had dpANS mandated that the compution
>of a pointer to x[-1] be a valid operation. Then machines for wich the
>mandated behavior is slow would be not used by people interested in high
>performance. The net effect could be salubrious for the computer industry in
>the long run.

No. A much more probable result would be widespread rejection of the C
standard, making things worse than before. ANSI does not have the power
to legislate conformance to standards -- that has to be voluntary. If
too many manufacturers, especially big ones, decline to conform to a
standard, it falls into disuse and is forgotten. Let us not forget that
the machine whose segmented architecture causes the biggest headaches for
pointer trickery is also the biggest-selling computer of all time. To get
a standard accepted (by the world, not just by ANSI), it is necessary --
distasteful, but necessary -- to restrain desires for social engineering,
and produce something that will work even on systems one does not like.

Richard Harter

unread,
Sep 17, 1988, 6:54:21 PM9/17/88
to
In article <85...@smoke.ARPA> gw...@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:

Re comments about x[-1] should be legal and should be in the standard.

>I doubt that any effect on the computer industry would have occurred
>other than reduced adherence to the postulated C standard. People
>writing portable applications would still not be able to compute
>&array[-1], since several compilers would ignore that requirement
>(benchmark speed is a far greater driving factor than the desires of
>a few sloppy programmers to compute non-existent addresses). What
>good would that situation accomplish? Better that the standard be
>widely followed and that programmers become better educated about
>actual portability considerations, than to encourage false hopes for
>availability of features that are difficult or detrimental to provide.

You may be right about reduced adherence, at least in this regard.
However the problem is not simply a matter of "sloppy" programming.
In C a pointer is a fairly anonymous object. What you are saying is
that it is a potential error to add or subtract an integer from a
pointer if the result is out of range. Very well, but what is that
range? Suppose a pointer is passed through a calling sequence. In
the function I have no way of knowing whether &x[n] will break for any
n other than 0. For that matter I have no way of knowing whether
x is a legal pointer!

In principle this is not right -- there is no way to write defensive
code to check on pointer validity. To be sure a "correct" program
never has an invalid pointer and all that but what about the rest of
us poor mortals?
--

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

Doug Gwyn

unread,
Sep 17, 1988, 9:03:38 PM9/17/88
to
In article <33...@cca.CCA.COM> g-...@XAIT.Xerox.COM (Richard Harter) writes:
>In C a pointer is a fairly anonymous object. What you are saying is
>that it is a potential error to add or subtract an integer from a
>pointer if the result is out of range. Very well, but what is that
>range?

Wherever the actual data is, plus a nonexistent extra member just past
the end of an array. But you knew that.

>Suppose a pointer is passed through a calling sequence. In
>the function I have no way of knowing whether &x[n] will break for any
>n other than 0. For that matter I have no way of knowing whether
>x is a legal pointer!

That's not quite the same issue. One presumes that your functions have
interface specifications, which if adhered to guarantee proper operation.
The code defining the function must of course implement those
specifications. The C language does not provide the means to completely
specify all relevant aspects of an interface in the C code itself, nor
does it require run-time enforcement of the interface specifications.
It does permit some degree of compile-time checking of the interface.

>In principle this is not right -- there is no way to write defensive
>code to check on pointer validity. To be sure a "correct" program
>never has an invalid pointer and all that but what about the rest of
>us poor mortals?

I suppose you should all learn ways to produce correct code. Many
such methods were figured out in the 1970s and should be part of
every professional programmer's repertoire by now.

If you ever get the chance to help design a brand-new programming
language, you might consider building in stronger aids for interface
specification checking. Ada tried that but didn't carry it far enough.

Chip Salzenberg

unread,
Sep 19, 1988, 4:47:01 PM9/19/88
to
According to ne...@ism780c.isc.com:

>But consider what might have happened had dpANS mandated that the compution
>of a pointer to x[-1] be a valid operation.

Okay, let's imagine: X3J11 says that x[-1] must be valid.
then: int must be 32 bits.
then: address space must be linear.
etc. until only the SPARC is conforming. (no smileys here)

Each time you make a "beneficial" restriction, you're condemning present
users of real, useful computers to the purgatory of enforced non-
conformance. I don't think anyone really wants X3J11 to make decisions
about which hardware will be permitted to run C programs.

In addition, it should be observed that on this issue, X3J11 stuck to its
charter and codified existing practice.

Henry Spencer

unread,
Sep 19, 1988, 5:30:23 PM9/19/88
to
In article <33...@cca.CCA.COM> g-...@XAIT.Xerox.COM (Richard Harter) writes:
>In C a pointer is a fairly anonymous object. What you are saying is
>that it is a potential error to add or subtract an integer from a
>pointer if the result is out of range. Very well, but what is that
>range?

The members of the array that the pointer points into, plus the special
case of just above the end of the array.

>Suppose a pointer is passed through a calling sequence. In
>the function I have no way of knowing whether &x[n] will break for any
>n other than 0. For that matter I have no way of knowing whether
>x is a legal pointer!

That's correct. It is the caller's responsibility to supply a pointer
that is adequate for the function's purposes, and the function writer's
responsibility to document those purposes well enough that the caller
knows what his responsibilities are. There is no way to check this at
runtime in conventional C implementations. That's C for you.

Richard Harter

unread,
Sep 20, 1988, 1:54:17 PM9/20/88
to
In article <1988Sep19.2...@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:
>In article <33...@cca.CCA.COM> g-...@XAIT.Xerox.COM (Richard Harter) writes:
>>In C a pointer is a fairly anonymous object. What you are saying is
>>that it is a potential error to add or subtract an integer from a
>>pointer if the result is out of range. Very well, but what is that
>>range?

>The members of the array that the pointer points into, plus the special
>case of just above the end of the array.

The question was rhetorical, in that I pointing out that there is
no way to determine from the pointer itself what its range was. I expect
it is a good thing to repeat the legal answer, since it is does seem to be
a complete mystery to some people :-).

>>Suppose a pointer is passed through a calling sequence. In
>>the function I have no way of knowing whether &x[n] will break for any
>>n other than 0. For that matter I have no way of knowing whether
>>x is a legal pointer!

>That's correct. It is the caller's responsibility to supply a pointer
>that is adequate for the function's purposes, and the function writer's
>responsibility to document those purposes well enough that the caller
>knows what his responsibilities are. There is no way to check this at
>runtime in conventional C implementations. That's C for you.

Such as it is :-). In theory this means that there is an entire class
of error checking that one can't do. For the most part this doesn't matter.
However it would be very nice if there were a library routine that would
tell you whether a pointer was legal or not. I am not much a fan of the
"if all the spec's and the interface definitions and the code are all correct
then you don't need error checking" school of programming. I rather like
the "be a skeptic and check and report the errors when you find them"
school of thought.

As a side note, one argument for making x[-1] legal is that it permits
you to use sentinels in both directions. I don't see that this is a
problem, regardless of architecture. All that is required is that nothing
be allocated on a segment boundary. However, as the man says, they way
it is is the way it is. There never was a machine, a language, or an
operating system without arcane restrictions. [Except lisp :-)]

Doug Gwyn

unread,
Sep 20, 1988, 4:44:53 PM9/20/88
to
In article <33...@XAIT.XEROX.COM> g-...@XAIT.Xerox.COM (Richard Harter) writes:
>As a side note, one argument for making x[-1] legal is that it permits
>you to use sentinels in both directions. I don't see that this is a
>problem, regardless of architecture. All that is required is that nothing
>be allocated on a segment boundary.

There is a considerable practical difference between this case and the
one for a pointer just past the last member of an array. The [-1] case
can require reservation of an arbitrary amount of unused address space
below an actual object, whereas the other case requires no more than a
byte (or a word, depending on the architecture) of space reserved above.

Richard Harter

unread,
Sep 21, 1988, 3:30:05 AM9/21/88
to
In article <85...@smoke.ARPA> gw...@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:

Good point. [For those who didn't catch it, the size of the object that
a pointer is pointing to can be a structure of (arbitrary) size. To allow
&x[-1] to be legal you have to leave enough space for an instance of the
structure (or array of structures or whatever) before the actual instance.]

Doug's claim that the other case (one past) need only require a word (or byte)
of memory at the end suggests a question that I don't know the answer to.
Suppose that x is an array of structures of length n. As we all know,
&x[n] is legal. But what about &x[n].item? If Doug's assertion is correct,
and I expect it is since he is quite knowledgable in these matters, then
it would seem to follow that &x[n].item is not guaranteed to be legal.

Mark Jones

unread,
Sep 21, 1988, 11:40:05 AM9/21/88
to
In article <1988Sep19.1...@ateng.uucp>, ch...@ateng.uucp (Chip Salzenberg) writes:
> According to ne...@ism780c.isc.com:
> >But consider what might have happened had dpANS mandated that the compution
> >of a pointer to x[-1] be a valid operation.
>
> Okay, let's imagine: X3J11 says that x[-1] must be valid.
> then: int must be 32 bits.

Excuse my ignorance, but why must an int be 32 bits for the above to work?

> then: address space must be linear.

Does X3J11 say that the contents of x[-1] must be valid?

Mark Jones

Henry Spencer

unread,
Sep 21, 1988, 12:39:15 PM9/21/88
to
In article <33...@XAIT.XEROX.COM> g-...@XAIT.Xerox.COM (Richard Harter) writes:
>As a side note, one argument for making x[-1] legal is that it permits
>you to use sentinels in both directions. I don't see that this is a
>problem, regardless of architecture. All that is required is that nothing
>be allocated on a segment boundary...

The situation unfortunately isn't as symmetrical as it looks, because
a pointer to an array element points to the *beginning* of the array
element. A pointer one past the end of an array points to the byte
(well, the addressing unit, whatever it is) following the array; a
pointer one past the beginning points to the byte (etc.) that is one
array-member-size before the beginning. Computing x[size] without
risk of overflow only requires that there be at least one byte between
the array and the end of a segment; computing x[-1] without risk of
underflow requires an entire array element between the array and the
start of the segment, which can get expensive if the elements are big
(consider multidimensional arrays).

The difference in costs was felt to be sufficient to justify a difference
in treatment. Both practices have been technically illegal all along,
so legitimizing both wasn't vitally necessary. Since x[size] gets used
a lot and is cheap to do, it was legalized. Since x[-1] was rather more
costly and is used less, it wasn't.

Maarten Litmaath

unread,