[net.lang.c] Fast code and no morals

wendt@megaron.UUCP (01/22/86)

Here's a version of calloc that breaks every rule of "structured"
programming ever invented -- and runs about twice as fast as a
vanilla version:

/* calloc - allocate and clear memory block */
#define CHARPERINT (sizeof(int)/sizeof(char))
#define NULL 0

char *calloc(num, size)
unsigned num, size;
    {
    register char *mp;
    char *malloc();
    register int *q, *qlim, m;

    num *= size;
    mp = malloc(num);
    if (mp == NULL) return (NULL);
    q = (int *) mp;
    qlim = (m = (num+CHARPERINT-1)/CHARPERINT) + (q = (int *)mp);

    switch (m & 7)
        do      {
                    *q++ = 0;
            case 7: *q++ = 0;
            case 6: *q++ = 0;
            case 5: *q++ = 0;
            case 4: *q++ = 0;
            case 3: *q++ = 0;
            case 2: *q++ = 0;
            case 1: *q++ = 0;
            case 0: ;
            } while (q < qlim);

    return (mp);
    }

.align  1
.globl  _calloc
.set    L32,0xf00
.data
.text
_calloc:.word   L32
mull2   8(ap),4(ap)
pushl   4(ap)
calls   $1,_malloc
movl    r0,r11
jneq    L37
clrl    r0
ret
L37:movl        r11,r10
pushl   $4
addl3   $3,4(ap),-(sp)
calls   $2,udiv
movl    r0,r8
ashl    $2,r0,r0
movl    r11,r10
addl3   r10,r0,r9
extzv   $0,$3,r8,r0
casel   r0,$0,$7
L2000000:
.word   L41-L2000000
.word   L49-L2000000
.word   L48-L2000000
.word   L47-L2000000
.word   L46-L2000000
.word   L45-L2000000
.word   L44-L2000000
.word   L43-L2000000
L38:movl        r11,r0
ret
L42:clrl        (r10)+
L43:clrl        (r10)+
L44:clrl        (r10)+
L45:clrl        (r10)+
L46:clrl        (r10)+
L47:clrl        (r10)+
L48:clrl        (r10)+
L49:clrl        (r10)+
L41:cmpl        r10,r9
jlss    L42
jbr     L38

gwyn@brl-tgr.UUCP (01/22/86)

> Here's a version of calloc that breaks every rule of "structured"
> programming ever invented -- and runs about twice as fast as a
> vanilla version:
> 
> /* calloc - allocate and clear memory block */
> #define CHARPERINT (sizeof(int)/sizeof(char))
> #define NULL 0
> 
> char *calloc(num, size)
> unsigned num, size;
>     {
>     register char *mp;
>     char *malloc();
>     register int *q, *qlim, m;
> 
>     num *= size;
>     mp = malloc(num);
>     if (mp == NULL) return (NULL);
>     q = (int *) mp;
>     qlim = (m = (num+CHARPERINT-1)/CHARPERINT) + (q = (int *)mp);
> 
>     switch (m & 7)
> 	do	{
> 		    *q++ = 0;
> 	    case 7: *q++ = 0;
> 	    case 6: *q++ = 0;
> 	    case 5: *q++ = 0;
> 	    case 4: *q++ = 0;
> 	    case 3: *q++ = 0;
> 	    case 2: *q++ = 0;
> 	    case 1: *q++ = 0;
> 	    case 0: ;
> 	    } while (q < qlim);
> 
>     return (mp);
>     }

So what?  This can be written "structured", and would be more
maintainable if it were.  Surely this is not an example of
recommended practice?

berry@zinfandel.UUCP (Berry Kercheval) (01/24/86)

In article <842@megaron.UUCP> wendt@megaron.UUCP writes:
>Here's a version of calloc that breaks every rule of "structured"
>programming ever invented -- and runs about twice as fast as a
>vanilla version:

And so on.  This is a well(?) known perversion of C and has been blessed 
by Dennis himself as ``legal'' C.  The first usage of it I know of
was by Tom Duff while he was at Lucasfilm and was reported in
this very newsgroup.  I append his tale for the edificication of
new netters:

/***** zinfandel:net.lang.c / alice!td /  3:57 am  May 11, 1984 */
Consider the following routine, abstracted from code which copies an
array of shorts into the Programmed IO data register of an Evans &
Sutherland Picture System II:

send(to, from, count)
register short *to, *from;
register count;
{
	do
		*to = *from++;
	while(--count>0);
}

(Obviously, this fails if the count is zero.)
The VAX C compiler compiles the loop into 2 instructions (a movw and
a sobleq, I think.)  As it turns out, this loop was the bottleneck in
a real-time animation playback program which ran too slowly by about 50%.
The standard way to get more speed out of something like this is to unwind
the loop a few times, decreasing the number of sobleqs.  When you do that,
you wind up with a leftover partial loop.  I usually handle this in C with
a switch that indexes a list of copies of the original loop body.  Of
course, if I were writing assembly language code, I'd just jump into the
middle of the unwound loop to deal with the leftovers.  Thinking about this
one day last October, the following implementation occurred to me:

send(to, from, count)
register short *to, *from;
register count;
{
	register n=(count+7)/8;
	switch(count%8){
	case 0:	do{	*to = *from++;
	case 7:		*to = *from++;
	case 6:		*to = *from++;
	case 5:		*to = *from++;
	case 4:		*to = *from++;
	case 3:		*to = *from++;
	case 2:		*to = *from++;
	case 1:		*to = *from++;
		}while(--n>0);
	}
}

Disgusting, no?  But it compiles and runs just fine on all known C compilers.
Dennis Ritchie has endorsed it as legal C.
I feel a combination of pride and revulsion at this discovery;
I think I'll name it after myself -- ``Duff's Device'' has a nice ring to it.

It amazes me that after 10 years of writing C there are still little corners
that I haven't explored fully.  (Actually, I have another revolting way to
use switches to implement interrupt driven state machines but it's too
horrid to go into.)

Many people (even Brian Kernighan?) have said that the worst feature of C is 
that switches don't break automatically before each case label.  This code forms
some sort of argument in that debate, but I'm not sure whether it's for or
against.

Tom Duff {ucbvax,decvax,ihnp4,...}!alice!td

Note:  Work reported herein was done while the author was an employee of
Lucasfilm Ltd., San Rafael, CA.
/* ---------- */
-- 
Berry Kercheval		Zehntel Inc.	(ihnp4!zehntel!zinfandel!berry)
(415)932-6900				(kerch@lll-tis.ARPA)

rb@ccivax (01/25/86)

> > Here's a version of calloc that breaks every rule of "structured"
> > programming ever invented -- and runs about twice as fast as a
> > vanilla version:
> > /* C code deleted to reduce traffic */
> > 
> 
> So what?  This can be written "structured", and would be more
> maintainable if it were.  Surely this is not an example of
> recommended practice?

True, that code was not what I would call a "Model for maintainability",
but when time or memory is limited (Try letting an RS-232 96kb link
do calloc when there's little or no flow control) maintainability
is a secondary issue (Who said that!!! :) ).

I would be interested in other examples of this type (like a real fast
version of "bcopy", or "bzero" ) even if it looked like chinese!!!

There are times when you need speed more than structure!

Anybody got a real fast copy example that can copy 97 bytes from an odd
address in less than 5 microseconds :) ?

pete@valid.UUCP (Pete Zakel) (01/25/86)

> > Here's a version of calloc that breaks every rule of "structured"
> > programming ever invented -- and runs about twice as fast as a
> > vanilla version:
> > 
> >     [fast code]
> 
> So what?  This can be written "structured", and would be more
> maintainable if it were.  Surely this is not an example of
> recommended practice?

Sure is recommended if you are optimizing for speed, which is what I assume
is being done here.  Since calloc is part of the system, and is assumed to
not have to be changed, maintainability is not the question.  Speed is the
answer.

"What do you get when you multiply 6 by 9?"
-Pete Zakel (..!{hplabs,amd,pyramid,ihnp4}!pesnta!valid!pete)

henry@utzoo.UUCP (Henry Spencer) (01/26/86)

> Here's a version of calloc that breaks every rule of "structured"
> programming ever invented...

Including the one that says "thou shalt explain anything obscure, for
verily that is what comments are for".  Violating the other rules is
sometimes in order, but not that one.  Comments are not noted for
slowing down execution.  Try them, you'll like them.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

dmr@dutoit.UUCP (01/27/86)

"No morals" applies less to the lack of comments than to the author's failure
to credit the idea to Tom Duff, invented it and who
posted it to this newsgroup a year or so ago.
"Don't shade your eyes, plagiarize!"

	Dennis Ritchie

ron@brl-smoke.ARPA (Ron Natalie <ron>) (01/28/86)

> > So what?  This can be written "structured", and would be more
> > maintainable if it were.  Surely this is not an example of
> > recommended practice?
> 
> Sure is recommended if you are optimizing for speed, which is what I assume
> is being done here.  Since calloc is part of the system, and is assumed to
> not have to be changed, maintainability is not the question.  Speed is the
> answer.
> 
If you are going to blast away at all the good features of a high level
language for the sake of speed, why don't you just program in assembler?

ka@hropus.UUCP (Kenneth Almquist) (01/28/86)

>>> Here's a version of calloc that breaks every rule of "structured"
>>> programming ever invented -- and runs about twice as fast as a
>>> vanilla version:
>> 
>> So what?  This can be written "structured", and would be more
>> maintainable if it were.  Surely this is not an example of
>> recommended practice?
>
> Sure is recommended if you are optimizing for speed, which is what I assume
> is being done here.  Since calloc is part of the system, and is assumed to
> not have to be changed, maintainability is not the question.  Speed is the
> answer.

"Assumed to not have to be changed!!!???"  I shouldn't even have to
mention the machine dependencies in this code or the coming of "void *";
I can assure you that any code that is used must be maintained.

As for the importance of speed, I have learnt the hard way to
think about what the code is supposed to do before I start hacking
at it.  The System V Release 2 calloc is not only clear and short
(three lines of C code), it is no doubt *faster* than the posted
calloc to boot.
				Kenneth Almquist
				ihnp4!houxm!hropus!ka	(official name)
				ihnp4!opus!ka		(shorter path)

jsdy@hadron.UUCP (Joseph S. D. Yao) (01/28/86)

In article <2085@dutoit.UUCP> dmr@dutoit.UUCP writes:
>"Don't shade your eyes, plagiarize!"

			-- Tom Lehrer
[A-hem!]	;-)
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}

laura@hoptoad.uucp (Laura Creighton) (01/28/86)

Guess what.  I just compiled this into 68000 assembler.  Now, I haven't
ever had to program in this particular assembler, but assembler is 
assembler -- even I could optimise the hell out of it.  God knows what
John Gilmore could do with it!  If you really want fast as hell, this is
the way to go.  If you want portable code, write portably.  But why on
earth do you want something which is not as fast as you could make it
with a half hours extra work *and* not portable and a bitch to maintain?

-- 
Laura Creighton		
sun!hoptoad!laura		(note new address!  l5 will still
ihnp4!hoptoad!laura		 work for a while....)
hoptoad!laura@lll-crg.arpa

sbs@valid.UUCP (Steven Brian McKechnie Sargent) (01/29/86)

*** REPLACE THIS LINE WITH YOUR MESSAGE ***

Um.  My 4bsd manual recommends

bzero(buf, n)
	char *buf;

which fills the ``n'' bytes starting at ``buf'' with 0.  You can
use this one or write your own; either way, the comments are in
the manual where everybody can find 'em, and the code doesn't have
to fit anybody's moral system but the maintainer's.  I appreciate
a tricky loop as much as the next guy, but in this case at least
the problem seems already to have been solved.

S.

johnl@ima.UUCP (01/29/86)

The loop unwound into switch hack has been around for a long time.  We used 
it at Yale in 1977 for a terminal emulator running on an 11/05 which was a 
front end to an 11/45 running the 6th edition Unix, recently upgraded from 
5th edition.  The terminal emulator spent too much of its time doing 
scrolling (including region scrolling) so we unwound the loops, using the 
switch hack to deal with the edges of regions.  Worked great then, works 
great now.  That particular time, it was concocted by John Mostenan and Bob 
Tuttle.  It's evidently been rediscovered a zillion times since.  

John Levine, ima!johnl 

PS: Writing our 11/05 C code so that the 11/45 C compiler wouldn't emit any 
instructions that the 11/05 couldn't execute, like multiply and divide, was 
the hard part.  

craig@dcl-cs.UUCP (Craig Wylie) (01/29/86)

In article <2085@dutoit.UUCP> dmr@dutoit.UUCP writes:
>"Don't shade your eyes, plagiarize!"
>
>	Dennis Ritchie
 "But always please to call it  Research"


-- 
UUCP:	 ...!seismo!mcvax!ukc!dcl-cs!craig| Post: University of Lancaster,
DARPA:	 craig%lancs.comp@ucl-cs 	  |	  Department of Computing,
JANET:	 craig@uk.ac.lancs.comp		  |	  Bailrigg, Lancaster, UK.
Phone:	 +44 524 65201 Ext. 4146   	  |	  LA1 4YR
Project: Cosmos Distributed Operating Systems Research

preece@ccvaxa.UUCP (01/29/86)

> "No morals" applies less to the lack of comments than to the author's
> failure to credit the idea to Tom Duff, invented it and who posted it
> to this newsgroup a year or so ago.  "Don't shade your eyes,
> plagiarize!" /* Written 11:42 pm  Jan 26, 1986 by dmr@dutoit.UUCP in
> ccvaxa:net.lang.c */
----------
The trick is simple enough to be re-discovered many times, cute
enough to be worth posting when discovered.  I see no reason
to assume the author knew of the previous posting.  Note the
slightly divergent treatment of the 0 case.  The Duff posting
was 20 months ago, which is a long time, in net terms.

There's nothing the matter with machine dependent code IF YOU
EXPLAIN IT AND MARK IT SO.  There is no such thing as a program
that runs too fast...

-- 
scott preece
gould/csd - urbana
uucp:	ihnp4!uiucdcs!ccvaxa!preece
arpa:	preece@gswd-vms

wendt@megaron.UUCP (01/29/86)

My apologies to Tom Duff.
I guess there *is* a moral here.

Alan W.

rb@ccivax.UUCP (rex ballard) (02/01/86)

In article <651@brl-smoke.ARPA> ron@brl-smoke.ARPA (Ron Natalie <ron>) writes:
>>> So what?  This can be written "structured" ...
>> Sure is recommended if you are optimizing for speed
>If you are going to blast away at all the good features of a high level
>language for the sake of speed, why don't you just program in assembler?

Assembler isn't portable, C is.

Since C is not sensitive to newlines that often, additional comments
could be added.

rb@ccivax.UUCP (rex ballard) (02/01/86)

In article <489@zinfandel.UUCP> berry@zinfandel.UUCP (Berry Kercheval) writes:
> [very bizarre code involving switches]
>I think I'll name it after myself -- ``Duff's Device'' has a nice ring to it.
>
>It amazes me that after 10 years of writing C there are still little corners
>that I haven't explored fully.  (Actually, I have another revolting way to
>use switches to implement interrupt driven state machines but it's too
>horrid to go into.)
>
>Tom Duff {ucbvax,decvax,ihnp4,...}!alice!td

Sounds kinky, I'd love to see it.

There is a point where 'Religion in Languages' is detremental.  Sure, if
a compiler/machine can produce better code in 'Structured C' than in
'Kludge C', that's great!  I know of only one machine where this is even
close to the case!  Other-wise, there are a few folks writing code for
controllers and things, that needs to be FAST, on a CPU that thinks
a call is an 'invitation to an interrupt'.

Tricks like quick-switches, and even 'function returning pointer to funtion...'
are very necessary.  For a good tutorial in 'Kludge C' look at the source
to Unix (Version 6 is particularly cute).

pete@valid.UUCP (Pete Zakel) (02/01/86)

> Comments are not noted for
> slowing down execution.  Try them, you'll like them.
> -- 
> 				Henry Spencer @ U of Toronto Zoology

An applicable comment from "Life During Valid" (a Valid specific version of
the Talking Heads' "Life During Wartime"):

	Burned all my comments, what good are comments?
	 They won't help me compile.
	My shortened program, core dumped in malloc.
	 Guess I'll debug for a while.

-Pete Zakel (..!{hplabs,amd,pyramid,ihnp4}!pesnta!valid!pete)

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (02/02/86)

> There is no such thing as a program that runs too fast...

Ahem.  I have seen some programs where so much attention was
paid to running speed that the question of whether the correct
results were being computed was ignored..

geoff@burl.UUCP (geoff) (02/02/86)

In article <2138@brl-tgr.ARPA> gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) writes:
>> There is no such thing as a program that runs too fast...
>
>Ahem.  I have seen some programs where so much attention was
>paid to running speed that the question of whether the correct
>results were being computed was ignored..

While I was in school some people were working on a 'paint' graphics program.
One of the operations was 'fill' to color large areas easily.  Kind of like
pouring a bottle of ink on the screen and letting it run any place not
bounded by other objects.  As I recall the fill code was written in Ikonas
microcode and was so fast that users were uncomfortable with it.  It was
artificially slowed down so that you could see the operation occurring
rather than *blink* its done.  Gave 'em a feeling of control or something.
	Does happen.  Rarely, tho'.

		geoff sherwood
		ihnp4!burl!geoff

SofPasuk@imagen.UUCP (Munach Rvi'i) (02/03/86)

> In article <651@brl-smoke.ARPA> ron@brl-smoke.ARPA (Ron Natalie <ron>) writes:
> >>> So what?  This can be written "structured" ...
> >> Sure is recommended if you are optimizing for speed
> >If you are going to blast away at all the good features of a high level
> >language for the sake of speed, why don't you just program in assembler?
> 
> Assembler isn't portable, C is.
> 
> Since C is not sensitive to newlines that often, additional comments
> could be added.

"C" is as portable as Stonehedge!!  At least assembler languages don't
pretend to be portable.  You know that there is work to go from system to
system.  The "security" of porting with "C" is the killer - the insidious
differences between implementations can kill you because you don't expect
them and can't plan well for them.

chris@umcp-cs.UUCP (Chris Torek) (02/04/86)

In article <231@imagen.UUCP> SofPasuk@imagen.UUCP writes:
> "C" is as portable as Stonehedge!! 

 ... and more about C code making hidden assumptions.

C is portable:

	/* echo */
	#include <stdio.h>

	main(argc, argv)
		register int argc;
		register char **argv;
	{
		register int i;

		argc--;
		for (i = 1; i <= argc; i++)
			printf("%s%c", argv[i], i < argc ? ' ' : '\n');
		exit(0);
	}

C is not portable:

	/* probebus */
	main(argc, argv)
	{
		register int i;
		register int size = 1;

		if (strcmp(argv[1], "i") == 0)	/* by ints */
			size = 4;
		for (i = 1 << 18; i < (1 << 19); i += size) {
			switch (size) {
			case 1:
				if (*(char *) i != 0) {
					printf("%x\n", i);
					exit(1);
				}
				break;
			case 4:
				if (*(int *) i != 0) {
					printf("%x\n", i);
					exit(1);
				}
				break;
			}
		}
		exit(0);
	}
	/* unportable assumptions: sizeof (int) == sizeof (char *);
	   *(char *)0 == ""; ints hold > 16 bits; type casts can
	   be used pretty much arbitrarily. */

It is not the language that makes code portable, though it can
help or hurt:  Programmers make code portable, or do not.

Incidentally, it is `Stonehenge'.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

henry@utzoo.UUCP (Henry Spencer) (02/06/86)

> > Assembler isn't portable, C is. ...
> 
> "C" is as portable as Stonehedge!!  At least assembler languages don't
> pretend to be portable.  You know that there is work to go from system to
> system.  The "security" of porting with "C" is the killer - the insidious
> differences between implementations can kill you because you don't expect
> them and can't plan well for them.

How curious.  At U of T we routinely move C code among half a dozen or so
different processors (more than that if you count different C compilers
for things like the 68000).  Compile it and it runs.

C's portability is more than just pretense.  Of course, you have to know
what you're doing when you write the code.  There is *no* "security" in
porting with C; it is easy to write unportable C, and writing portable
C takes knowledge, care, and attention.  Once you get used to it, it's
not hard.  We can and do plan for the aspects that vary between machines.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

levy@ttrdc.UUCP (Daniel R. Levy) (02/09/86)

<Oh oh here it comes.  Watch out boy, it'll chew you up! \
Oh oh here it comes.  The LINE EATER!  [Line eater]>

In article <3032@umcp-cs.UUCP>, chris@umcp-cs.UUCP (Chris Torek) writes:
>
>C is portable:
>
>	/* echo */
>	#include <stdio.h>
>
>	main(argc, argv)
>		register int argc;
>		register char **argv;
>	{
>		register int i;
>
>		argc--;
>		for (i = 1; i <= argc; i++)
>			printf("%s%c", argv[i], i < argc ? ' ' : '\n');
>		exit(0);
>	}
>--
>In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)

What about a system where it is impossible to give command line arguments to a
program, like the early-stone-age card reading IBM systems?   Not all C runs
on Unix ya know....  (Is C only allowed to run on machines that DO allow
command line arguments?  What does the proposed ANSI C standard say about this?)
Would this program just get run with an argc of 0 in the case of a stone
age system?  As a matter of fact, must a system support both upper and lower
case characters to support C?  (Would Cyber-type machines with 6 bit character
codes be out of the running?)  Perhaps nobody these days would WANT such a sys-
tem, rendering the point moot, but for the sake of argument :-), what if someone
had such a system and wanted to keep on using it, but with C rather than say,
Fortran (which would have no trouble with the absence of command line arguments
and the single case of characters)?
-- 
 -------------------------------    Disclaimer:  The views contained herein are
|       dan levy | yvel nad      |  my own and are not at all those of my em-
|         an engihacker @        |  ployer or the administrator of any computer
| at&t computer systems division |  upon which I may hack.
|        skokie, illinois        |
 --------------------------------   Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
						vax135}!ttrdc!levy

gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/10/86)

In article <720@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
>What about a system where it is impossible to give command line arguments to a
>program, like the early-stone-age card reading IBM systems?   Not all C runs
>on Unix ya know....  (Is C only allowed to run on machines that DO allow
>command line arguments?  What does the proposed ANSI C standard say about this?)
>Would this program just get run with an argc of 0 in the case of a stone
>age system?  As a matter of fact, must a system support both upper and lower
>case characters to support C?  (Would Cyber-type machines with 6 bit character
>codes be out of the running?)  Perhaps nobody these days would WANT such a sys-
>tem, rendering the point moot, but for the sake of argument :-), what if someone
>had such a system and wanted to keep on using it, but with C rather than say,
>Fortran (which would have no trouble with the absence of command line arguments
>and the single case of characters)?

In a hosted (as opposed to stand-alone) environment, yes, C requires
that programs be able to obtain arguments specified at the time they
are run.  The Software Tools people have accomplished this on
virtually every major mainframe and minicomputer OS, so it is doable.

Yes, C requires support of both upper- and lower-case characters.
Modern Cybers claim to have support for 8- or 12-bit characters.

Nobody promised that C could be implemented on an abacus.

rb@ccivax.UUCP (rex ballard) (02/11/86)

In article <6365@utzoo.UUCP> henry@utzoo.UUCP (Henry Spencer) writes:
>> > Assembler isn't portable, C is. ...
>> 
>> "C" is as portable as Stonehedge!!  At least assembler languages don't
>> pretend to be portable.
>
>How curious.  At U of T we routinely move C code among half a dozen or so
>different processors (more than that if you count different C compilers
>for things like the 68000).  Compile it and it runs.
>
>C's portability is more than just pretense.  Of course, you have to know
>what you're doing when you write the code.

When the same application or small routine has to on an 8085, 8086, 68000,
68010, PDP-11, and a VAX, and is subject to FREQUENT enhancement, and
only two machines run UNIX, the less written in assembler, the better.

Standard practice in this case is to run everything, including libraries
through lint, all 8 compilers (Large and small model 68K on native and
non-native), and be real specific about types.

This is much better than having to maintain 8 different assembler versions.

Even if 'fast but no morals' doesn't optimize as well on the VAX as it does
on the 68K, it still runs.  The examples are common profiler hot spots.
bcopy(dest,src,len)
REG char *dest,*src;
REG USHORT len;
{
while(len--)
   *dest++=*src++;
}

may look prettier than

bcopy(dest,src,len)
REG char *dest,*src;
REG USHORT len;
{
if(len)
do{
  *dest++=*src++;
  }while(--len)
}

but when you are calling bcopy to move 2k before the next
interrupt hits, the extra 10us per iteration (dbgt vs. test,bra)
can get real costly.  Adding automatic backward detection (used in editors)
would be difficult in assembler, but not in C.

dyer@dec-vaxuum.UUCP (02/11/86)

Re: fast code and no morals_______________________________________

> exit(0);

    This isn't portable to VMS.  (-: Does anybody care about VMS,
though? :-)  0 is an undefined status code in VMS!
		<_Jym_>
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::'  ::  `::::             Jym Dyer             ::::'  ::  `::::
::'    ::    `::       Dracut, Massachusetts      ::'    ::    `::
::     ::     ::::::::::::::::::::::::::::::::::::::     ::     ::
::   .::::.   ::   DYER%VAXUUM.DEC@DECWRL.ARPA    ::   .::::.   ::
::..:' :: `:..::  {allegra|decvax|ihnp4|ucbvax}   ::..:' :: `:..::
::::.  ::  .:::: decwrl!dec-rhea!dec-vaxuum!dyer  ::::'  ::  `::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

emjej@uokvax.UUCP (02/11/86)

/* Written  6:35 pm  Feb  8, 1986 by levy@ttrdc.UUCP in net.lang.c */
What about a system where it is impossible to give command line arguments to a
program, like the early-stone-age card reading IBM systems?   Not all C runs
on Unix ya know....  (Is C only allowed to run on machines that DO allow
command line arguments?  What does the proposed ANSI C standard say about this?)
/* End of text from net.lang.c */

Actually, there are times one might want to parse the command line oneself.
Consider the joys of the quoting and so forth required to type a RFC822
address on a command line so as to make it past the shell, etc. to a mailer.
I'll say no more, since it's been discussed at vociferous length before
(mostly flamage at anyone daring to suggest something other than what Unix
does).

					James Jones

rb@ccivax.UUCP (rex ballard) (02/13/86)

In article <720@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes:
>
>What about a system where it is impossible to give command line arguments to a
>program, like the early-stone-age card reading IBM systems?   Not all C runs
>on Unix ya know.... 

I have been using C on several machines and OS's, some so proprietary they
don't even have names.  Much of the same code can be ported across several
of them.

>(Is C only allowed to run on machines that DO allow
>command line arguments?

No, but you may have to change the argument parser (main() in most cases)
to get the arguments from files, cards, tape, tty..., but this involves
changing only one routine, not the whole application.

Unix 'cheats'! There is a routine called 'start(), that sets up certain
internal arguments, file I/O buffers, assignments... calls main() (your
program) and then cleanup() which closes files, and cleans up memory...
Do the same with your 'stone age system, and the program may even run
unmodified.

>Would this program just get run with an argc of 0 in the case of a stone
>age system?

This largely depends on the compiler.  One of our compilers would actually
allow only one argument from the OS, this was used as a pointer to a block
on disk where the arguments were stored.

>As a matter of fact, must a system support both upper and lower
>case characters to support C?  (Would Cyber-type machines with 6 bit character
>codes be out of the running?)

One of our compilers only supported upper case characters, but code could
be written it and UNIX (for debug purposes) with almost no modification.
It was later replaced by a upper/lower case compiler and all properly
written code (linted), worked.  V7 lint did not identify non-portable
character comparisons, but the latest 4.2 version does.

One can even write a 'stdio library' for RT-11 style file systems.
C has been available for CP/M for a while now, and works fairly well.

Not EVERYTHING written in C will work on EVERY machine UNMODIFIED, but
less modification will be required when porting between systems than
something written in assembler.  This is especially important when the
target machine/OS does not have a strong debugger or support tools.

gwyn@BRL.ARPA (02/16/86)

If VMS does not support exit(0) as successful termination,
then VMS is WRONG and needs to fix their exit() routine.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/16/86)

>Even if 'fast but no morals' doesn't optimize as well on the VAX as it does
>on the 68K, it still runs.  The examples are common profiler hot spots.
>bcopy(dest,src,len)
>REG char *dest,*src;
>REG USHORT len;
>{
>while(len--)
>   *dest++=*src++;
>}
>
>may look prettier than
>
>bcopy(dest,src,len)
>REG char *dest,*src;
>REG USHORT len;
>{
>if(len)
>do{
>  *dest++=*src++;
>  }while(--len)
>}
>
>but when you are calling bcopy to move 2k before the next
>interrupt hits, the extra 10us per iteration (dbgt vs. test,bra)
>can get real costly.  Adding automatic backward detection (used in editors)
>would be difficult in assembler, but not in C.

Neither of these examples uses obscure code (except for your
redefining C keywords for no good reason).  Also, neither
one is the best implementation of bcopy() on most machines.
One can do much better than byte transfers within a loop.
If you're going to worry about efficiency, do it right; use
the memcpy() library routine which some system programmer
has tuned for fastest possible block transfer, rather than
writing your own.

meissner@dg_rtp.UUCP (02/17/86)

In article <814@brl-smoke.ARPA> gwyn@brl.ARPA writes:
>In a hosted (as opposed to stand-alone) environment, yes, C requires
>that programs be able to obtain arguments specified at the time they
>are run.  The Software Tools people have accomplished this on
>virtually every major mainframe and minicomputer OS, so it is doable.
>
>Yes, C requires support of both upper- and lower-case characters.
>Modern Cybers claim to have support for 8- or 12-bit characters.
>

I believe Doug already knows this, but ANSI C does not require command line
arguments to be dual-case.  If the environment can only support one case,
command line args MUST be mapped to lower case.
	Michael Meissner

SofPasuk@imagen.UUCP (Munach Rvi'i) (02/17/86)

> In article <6365@utzoo.UUCP> henry@utzoo.UUCP (Henry Spencer) writes:
> >> > Assembler isn't portable, C is. ...
> >> 
> >> "C" is as portable as Stonehedge!!  At least assembler languages don't
> >> pretend to be portable.
> >
> >How curious.  At U of T we routinely move C code among half a dozen or so
> >different processors (more than that if you count different C compilers
> >for things like the 68000).  Compile it and it runs.
> >
> >C's portability is more than just pretense.  Of course, you have to know
> >what you're doing when you write the code.
> 
> When the same application or small routine has to on an 8085, 8086, 68000,
> 68010, PDP-11, and a VAX, and is subject to FREQUENT enhancement, and
> only two machines run UNIX, the less written in assembler, the better.
> 
> Standard practice in this case is to run everything, including libraries
> through lint, all 8 compilers (Large and small model 68K on native and
> non-native), and be real specific about types.
> 
> This is much better than having to maintain 8 different assembler versions.
> 
> ...
> 

The point about the "C" being as portable as Stonehenge was made NOT to
imply that programs should be routinely written in Assembler Language
(pun not intended), but rather that porting of programs written in "C"
has its own different set of problems, the solution to some of which are
noted above.  This is very obvious to organizations, such as mine, that
distribute "C"-based software for use on many different host systems, all of
which allegedly have "standard UNIX" and "standard C" (whatever "standard"
means these days).

Of course, we would never be able to distribute our software for so many
different host systems if we were required to write the code in Assembler,
but, on the other hand, we must go through significant coding gymnastics to
assure the portability including sticking to the "least common multiple" of
language features and "detuning" programs due to the compiler restrictions
(authors call them features, of course) on some systems.  We don't have the
luxury of telling our customers "too bad, your system doesn't have a good
or standard enough C compiler!"

lars@acc.arpa (02/18/86)

> Date: 11 Feb 86 13:40:30 GMT
> 
> > exit(0);
> 
>     This isn't portable to VMS.  (-: Does anybody care about VMS,
> though? :-)  0 is an undefined status code in VMS!
> 		<_Jym_> dyer@dec-vaxuum.uucp

> Date:     Sat, 15 Feb 86 21:43:34 EST
> 
> If VMS does not support exit(0) as successful termination,
> then VMS is WRONG and needs to fix their exit() routine.
>           Doug Gwyn (VLD/VMB) <gwyn@BRL.ARPA>

I know this is naive, but then this flock is full of naive users...
Doug, where exactly do Kernighan & Ritchie specify the semantics of
the exit() procedure ?

The common semantics seem to me to be "return to the surrounding
operating system level, using the argument value as the return code".
Unfortunately for portability, UN*X and VMS have different ideas about
the semantics of program return codes, but you can't say VMS is WRONG
just because it's DIFFERENT unless you can quote chapter and verse.

Does the ANSI draft specify semantics for system calls ?

			/ Lars Poulsen
			  Advanced Computer Communications
			 <Lars @ ACC.ARPA>

------

jon@csvax.caltech.edu (02/19/86)

>   > Date:	Sat, 15 Feb 86 21:43:34 EST
>   >
>   > If VMS does not support exit(0) as successful termination,
>   > then VMS is WRONG and needs to fix their exit() routine.
>   >		Doug Gwyn (VLD/VMB) <gwyn@BRL.ARPA>
>
>   ...
>   Does the ANSI draft specify semantics for system calls ?
>
>			    / Lars Poulsen
>			      Advanced Computer Communications
>			     <Lars @ ACC.ARPA>

    To be nitpicking,  exit()  is  not	a  system  call,  although  it
    probably invokes one. In answer to	the  question,	the  April  30
    1985 draft says (Section D.10.4.2):

	    void exit(int status);

	    Finally, control is returned to the host environment.   If
	the value of status is zero, the status returned is SUCCESSFUL
	TERMINATION; otherwise an implementation-defined form  of  the
	status UNSUCCESSFUL TERMINATION is returned.

    Currently exiting  with  status  0	on  VMS  generates  a  message
complaining about the unknown exit status 0. I find this most annoying
in trying to port code from Unix (actually there  are  lots  of  other
misfeatures of VMS that qualify as MOST annoying, but...)

    -- Jon Leech (jon@csvax.caltech.edu)
    __@/

JOSH%YKTVMH.BITNET@wiscvm.ARPA (Josh Knight) (02/19/86)

 > Date: 17 Feb 86 14:46:00 PST
 >
 > > Date:     Sat, 15 Feb 86 21:43:34 EST
 > >
 > > If VMS does not support exit(0) as successful termination,
 > > then VMS is WRONG and needs to fix their exit() routine.
 > >           Doug Gwyn (VLD/VMB) <gwyn@BRL.ARPA>
 >
 > I know this is naive, but then this flock is full of naive users...
 > Doug, where exactly do Kernighan & Ritchie specify the semantics of
 > the exit() procedure ?
 >
 > The common semantics seem to me to be "return to the surrounding
 > operating system level, using the argument value as the return code".
 > Unfortunately for portability, UN*X and VMS have different ideas about
 > the semantics of program return codes, but you can't say VMS is WRONG
 > just because it's DIFFERENT unless you can quote chapter and verse.
 >
 > Does the ANSI draft specify semantics for system calls ?
 >
 >             / Lars Poulsen
 >               Advanced Computer Communications
 >              <Lars @ ACC.ARPA>
 >

Chapter and verse:


From ANSI C Standard Draft Version dated 11 August 1985,
Section D.10.4.2, "The exit function" (third paragraph):

     Finally, control is returned to the host environment.  If the
     value of *status* is zero, the status returned is *successful
     termination*; otherwise an implementation-defined form of the
     status *unsuccessful termination* is returned.

From K&R, Chapter 7, Section 7, "Error Handling - Stderr and Exit"
p. 154, next to the last paragraph:

     The program also uses the standard library function *exit*, which
     terminates program execution when it is called.  The argument of
     *exit* is available to whatever process called this one, so the
     success or failure of the program can be tested by another program
     that uses this one as a sub-process.  By convention, a return value
     of 0 signals that all is well, and various non-zero values signal
     abnormal situations.



Of course, any opinions, expressed or implied are mine and not my
employers...

			Josh Knight
			IBM T.J. Watson Research Center
josh@yktvmh.BITNET,  josh.yktvmh@ibm-sj.arpa

chris@umcp-cs.UUCP (Chris Torek) (02/19/86)

In article <1015@brl-smoke.ARPA> lars@acc.arpa writes:

>> If VMS does not support exit(0) as successful termination,
>> then VMS is WRONG and needs to fix their exit() routine.
>>           Doug Gwyn (VLD/VMB) <gwyn@BRL.ARPA>

>The common semantics seem to me to be "return to the surrounding
>operating system level, using the argument value as the return code".

This is arguably valid; but I argue that a better definition is
`quit this program; argument == 0 implies success, anything else
implies failure'.  This is *not* part of the `K&R bible'; it simply
is a good idea given the large existing body of Unix C code that
makes that assumption.

>Does the ANSI draft specify semantics for system calls ?

No, but it does specify semantics for exit().  Who ever said exit()
was a system call?  (And in fact, it is not a system call in any
`current' Unix: it is a stdio routine.  The system call is _exit().)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

gwyn@BRL.ARPA (VLD/VMB) (02/20/86)

Yes, but C requires both upper- and lower-case support for
program text itself, which rules out implementation on real
dinosaurs (hurray!).

perl@rdin.UUCP (Robert Perlberg) (02/20/86)

>I know this is naive, but then this flock is full of naive users...
>Doug, where exactly do Kernighan & Ritchie specify the semantics of
>the exit() procedure ?
>
>                                           you can't say VMS is WRONG
>just because it's DIFFERENT unless you can quote chapter and verse.
>
>Does the ANSI draft specify semantics for system calls ?

K&R, Chapter 7, page 154, verse 5 (and I quote -- uh-hum):

"The program also uses the standard library function exit, which
terminates program execution when it is called.  The argument of exit
is available to whatever process called this one, so the success or
failure of the program can be tested by another program that uses this
one as a subprocess.  By convention, a return value of 0 signals that
all is well, and various non-zero values signal abnormal situations."

Amen.

Let's get real, though.  I don't really care about how something is
defined by K&R or ANSI or any so-called authority.  All I care about is
being able to copy a bunch of code onto a system, compile it, and have
it work.  If the designers of VAX C endowed it with an exit() function,
it's not because they saw it in K&R, it's because they wanted VAX C to
be able to compile and run the vast body of C code "out there".  The
VAX C manual is loaded with references to UNIX and has many functions
which are clearly intended to mimic UNIX (take a look at stat()).  You
could quote K&R till doomsday and it wouldn't make existing code run on
existing systems until you wake up and take a look at how things are
done in the real world and adapt to it.  You're a fine one to be
calling others "naive".

Robert Perlberg
Resource Dynamics Inc.
New York
{philabs|delftcc}!rdin!perl